Repository: goccy/go-json
Pull request #356 (2022-03-24 20:14:25)

feat: add DebugWith option
add DebugWith option


Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9139b9b..5aa45b3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,19 +1,3 @@
-# v0.9.6 - 2022/03/22
-
-### Fix bugs
-
-* Correct the handling of the minimum value of int type for decoder ( #344 )
-* Fix bugs of stream decoder's bufferSize ( #349 )
-* Add a guard to use typeptr more safely ( #351 )
-
-### Improve decoder performance
-
-* Improve escapeString's performance ( #345 )
-
-### Others
-
-* Update go version for CI ( #347 )
-
 # v0.9.5 - 2022/03/04
 
 ### Fix bugs
diff --git a/encode.go b/encode.go
index c9527c0..4bd899f 100644
--- a/encode.go
+++ b/encode.go
@@ -3,6 +3,7 @@ package json
 import (
 	"context"
 	"io"
+	"os"
 	"unsafe"
 
 	"github.com/goccy/go-json/internal/encoder"
@@ -62,6 +63,7 @@ func (e *Encoder) encodeWithOption(ctx *encoder.RuntimeContext, v interface{}, o
 		ctx.Option.Flag |= encoder.HTMLEscapeOption
 	}
 	ctx.Option.Flag |= encoder.NormalizeUTF8Option
+	ctx.Option.DebugOut = os.Stdout
 	for _, optFunc := range optFuncs {
 		optFunc(ctx.Option)
 	}
diff --git a/internal/decoder/compile.go b/internal/decoder/compile.go
index bf17d1b..b2e9f57 100644
--- a/internal/decoder/compile.go
+++ b/internal/decoder/compile.go
@@ -154,9 +154,6 @@ func compileMapKey(typ *runtime.Type, structName, fieldName string, structTypeTo
 	if runtime.PtrTo(typ).Implements(unmarshalTextType) {
 		return newUnmarshalTextDecoder(runtime.PtrTo(typ), structName, fieldName), nil
 	}
-	if typ.Kind() == reflect.String {
-		return newStringDecoder(structName, fieldName), nil
-	}
 	dec, err := compile(typ, structName, fieldName, structTypeToDecoder)
 	if err != nil {
 		return nil, err
diff --git a/internal/encoder/option.go b/internal/encoder/option.go
index dcec8f2..82d5ce3 100644
--- a/internal/encoder/option.go
+++ b/internal/encoder/option.go
@@ -1,6 +1,9 @@
 package encoder
 
-import "context"
+import (
+	"context"
+	"io"
+)
 
 type OptionFlag uint8
 
@@ -19,6 +22,7 @@ type Option struct {
 	Flag        OptionFlag
 	ColorScheme *ColorScheme
 	Context     context.Context
+	DebugOut    io.Writer
 }
 
 type EncodeFormat struct {
diff --git a/internal/encoder/vm/debug_vm.go b/internal/encoder/vm/debug_vm.go
index 05509fe..fbbc0de 100644
--- a/internal/encoder/vm/debug_vm.go
+++ b/internal/encoder/vm/debug_vm.go
@@ -16,16 +16,17 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet)
 		}
 
 		if err := recover(); err != nil {
-			fmt.Println("=============[DEBUG]===============")
-			fmt.Println("* [TYPE]")
-			fmt.Println(codeSet.Type)
-			fmt.Printf("\n")
-			fmt.Println("* [ALL OPCODE]")
-			fmt.Println(code.Dump())
-			fmt.Printf("\n")
-			fmt.Println("* [CONTEXT]")
-			fmt.Printf("%+v\n", ctx)
-			fmt.Println("===================================")
+			w := ctx.Option.DebugOut
+			fmt.Fprintln(w, "=============[DEBUG]===============")
+			fmt.Fprintln(w, "* [TYPE]")
+			fmt.Fprintln(w, codeSet.Type)
+			fmt.Fprintf(w, "\n")
+			fmt.Fprintln(w, "* [ALL OPCODE]")
+			fmt.Fprintln(w, code.Dump())
+			fmt.Fprintf(w, "\n")
+			fmt.Fprintln(w, "* [CONTEXT]")
+			fmt.Fprintf(w, "%+v\n", ctx)
+			fmt.Fprintln(w, "===================================")
 			panic(err)
 		}
 	}()
diff --git a/internal/encoder/vm_color/debug_vm.go b/internal/encoder/vm_color/debug_vm.go
index 6a6a33d..925f61e 100644
--- a/internal/encoder/vm_color/debug_vm.go
+++ b/internal/encoder/vm_color/debug_vm.go
@@ -16,16 +16,17 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet)
 
 	defer func() {
 		if err := recover(); err != nil {
-			fmt.Println("=============[DEBUG]===============")
-			fmt.Println("* [TYPE]")
-			fmt.Println(codeSet.Type)
-			fmt.Printf("\n")
-			fmt.Println("* [ALL OPCODE]")
-			fmt.Println(code.Dump())
-			fmt.Printf("\n")
-			fmt.Println("* [CONTEXT]")
-			fmt.Printf("%+v\n", ctx)
-			fmt.Println("===================================")
+			w := ctx.Option.DebugOut
+			fmt.Fprintln(w, "=============[DEBUG]===============")
+			fmt.Fprintln(w, "* [TYPE]")
+			fmt.Fprintln(w, codeSet.Type)
+			fmt.Fprintf(w, "\n")
+			fmt.Fprintln(w, "* [ALL OPCODE]")
+			fmt.Fprintln(w, code.Dump())
+			fmt.Fprintf(w, "\n")
+			fmt.Fprintln(w, "* [CONTEXT]")
+			fmt.Fprintf(w, "%+v\n", ctx)
+			fmt.Fprintln(w, "===================================")
 			panic(err)
 		}
 	}()
diff --git a/internal/encoder/vm_color_indent/debug_vm.go b/internal/encoder/vm_color_indent/debug_vm.go
index a68bbf6..dd4cd48 100644
--- a/internal/encoder/vm_color_indent/debug_vm.go
+++ b/internal/encoder/vm_color_indent/debug_vm.go
@@ -16,16 +16,17 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet)
 
 	defer func() {
 		if err := recover(); err != nil {
-			fmt.Println("=============[DEBUG]===============")
-			fmt.Println("* [TYPE]")
-			fmt.Println(codeSet.Type)
-			fmt.Printf("\n")
-			fmt.Println("* [ALL OPCODE]")
-			fmt.Println(code.Dump())
-			fmt.Printf("\n")
-			fmt.Println("* [CONTEXT]")
-			fmt.Printf("%+v\n", ctx)
-			fmt.Println("===================================")
+			w := ctx.Option.DebugOut
+			fmt.Fprintln(w, "=============[DEBUG]===============")
+			fmt.Fprintln(w, "* [TYPE]")
+			fmt.Fprintln(w, codeSet.Type)
+			fmt.Fprintf(w, "\n")
+			fmt.Fprintln(w, "* [ALL OPCODE]")
+			fmt.Fprintln(w, code.Dump())
+			fmt.Fprintf(w, "\n")
+			fmt.Fprintln(w, "* [CONTEXT]")
+			fmt.Fprintf(w, "%+v\n", ctx)
+			fmt.Fprintln(w, "===================================")
 			panic(err)
 		}
 	}()
diff --git a/internal/encoder/vm_indent/debug_vm.go b/internal/encoder/vm_indent/debug_vm.go
index 4cfd17a..9939538 100644
--- a/internal/encoder/vm_indent/debug_vm.go
+++ b/internal/encoder/vm_indent/debug_vm.go
@@ -16,16 +16,17 @@ func DebugRun(ctx *encoder.RuntimeContext, b []byte, codeSet *encoder.OpcodeSet)
 
 	defer func() {
 		if err := recover(); err != nil {
-			fmt.Println("=============[DEBUG]===============")
-			fmt.Println("* [TYPE]")
-			fmt.Println(codeSet.Type)
-			fmt.Printf("\n")
-			fmt.Println("* [ALL OPCODE]")
-			fmt.Println(code.Dump())
-			fmt.Printf("\n")
-			fmt.Println("* [CONTEXT]")
-			fmt.Printf("%+v\n", ctx)
-			fmt.Println("===================================")
+			w := ctx.Option.DebugOut
+			fmt.Fprintln(w, "=============[DEBUG]===============")
+			fmt.Fprintln(w, "* [TYPE]")
+			fmt.Fprintln(w, codeSet.Type)
+			fmt.Fprintf(w, "\n")
+			fmt.Fprintln(w, "* [ALL OPCODE]")
+			fmt.Fprintln(w, code.Dump())
+			fmt.Fprintf(w, "\n")
+			fmt.Fprintln(w, "* [CONTEXT]")
+			fmt.Fprintf(w, "%+v\n", ctx)
+			fmt.Fprintln(w, "===================================")
 			panic(err)
 		}
 	}()
diff --git a/option.go b/option.go
index 0138d77..af400a4 100644
--- a/option.go
+++ b/option.go
@@ -1,6 +1,8 @@
 package json
 
 import (
+	"io"
+
 	"github.com/goccy/go-json/internal/decoder"
 	"github.com/goccy/go-json/internal/encoder"
 )
@@ -39,6 +41,13 @@ func Debug() EncodeOptionFunc {
 	}
 }
 
+// DebugWith sets the destination to write debug messages.
+func DebugWith(w io.Writer) EncodeOptionFunc {
+	return func(opt *EncodeOption) {
+		opt.DebugOut = w
+	}
+}
+
 // Colorize add an identifier for coloring to the string of the encoded result.
 func Colorize(scheme *ColorScheme) EncodeOptionFunc {
 	return func(opt *EncodeOption) {


Test patch:
diff --git a/decode_test.go b/decode_test.go
index 57d9c6a..3820173 100644
--- a/decode_test.go
+++ b/decode_test.go
@@ -3889,21 +3889,3 @@ func TestIssue348(t *testing.T) {
 		}
 	}
 }
-
-type issue342 string
-
-func (t *issue342) UnmarshalJSON(b []byte) error {
-	panic("unreachable")
-}
-
-func TestIssue342(t *testing.T) {
-	var v map[issue342]int
-	in := []byte(`{"a":1}`)
-	if err := json.Unmarshal(in, &v); err != nil {
-		t.Errorf("unexpected error: %v", err)
-	}
-	expected := 1
-	if got := v["a"]; got != expected {
-		t.Errorf("unexpected result: got(%v) != expected(%v)", got, expected)
-	}
-}
diff --git a/encode_test.go b/encode_test.go
index 469b655..92f4304 100644
--- a/encode_test.go
+++ b/encode_test.go
@@ -477,7 +477,8 @@ func TestDebugMode(t *testing.T) {
 			t.Fatal("expected error")
 		}
 	}()
-	json.MarshalWithOption(mustErrTypeForDebug{}, json.Debug())
+	var buf bytes.Buffer
+	json.MarshalWithOption(mustErrTypeForDebug{}, json.Debug(), json.DebugWith(&buf))
 }
 
 func TestIssue116(t *testing.T) {