Repository: go-logr/logr (go)

Issue:
funcr: invalid json when omitting fields
Hello !

When using `funcr` implementation with JSON formatter, produced JSON is invalid when omitting fields using `json` struct tag.

## How to reproduce

[Go Playground](https://go.dev/play/p/TM8lUdSVyIV)

```go
type Foo struct {
	Bar string `json:"-"`
	Baz string `json:"baz"`
}

func main() {
	logger := funcr.NewJSON(
		func(obj string) { fmt.Println(obj) },
		funcr.Options{},
	)
	logger.Info("", "foo", Foo{})
}
```

### Expected output

```json
{"logger":"","level":0,"msg":"","foo":{"baz":""}}
```

### Got output

```json
{"logger":"","level":0,"msg":"","foo":{,"baz":""}}
```

Notice the extra comma before `baz` key.

A quick investigation pointed this [line](https://github.com/go-logr/logr/blob/v1.2.3/funcr/funcr.go#L481) as the potential issue.

Thanks for your help !

Pull request:
funcr: JSON invalid output with 1st field omitted
We can't just check for `i > 0` - the leading field or fields could have been omitted.

Fixes #157 

Patch:
diff --git a/funcr/funcr.go b/funcr/funcr.go
index e83e408..0baf003 100644
--- a/funcr/funcr.go
+++ b/funcr/funcr.go
@@ -448,6 +448,7 @@ func (f Formatter) prettyWithFlags(value interface{}, flags uint32, depth int) s
 		if flags&flagRawStruct == 0 {
 			buf.WriteByte('{')
 		}
+		printComma := false // testing i>0 is not enough because of JSON omitted fields
 		for i := 0; i < t.NumField(); i++ {
 			fld := t.Field(i)
 			if fld.PkgPath != "" {
@@ -479,9 +480,10 @@ func (f Formatter) prettyWithFlags(value interface{}, flags uint32, depth int) s
 			if omitempty && isEmpty(v.Field(i)) {
 				continue
 			}
-			if i > 0 {
+			if printComma {
 				buf.WriteByte(',')
 			}
+			printComma = true // if we got here, we are rendering a field
 			if fld.Anonymous && fld.Type.Kind() == reflect.Struct && name == "" {
 				buf.WriteString(f.prettyWithFlags(v.Field(i).Interface(), flags|flagRawStruct, depth+1))
 				continue


Test patch:
diff --git a/funcr/funcr_test.go b/funcr/funcr_test.go
index 20b26a5..8af3970 100644
--- a/funcr/funcr_test.go
+++ b/funcr/funcr_test.go
@@ -106,6 +106,7 @@ func (t Terrorpanic) Error() string {
 }
 
 type TjsontagsString struct {
+	String0 string `json:"-"`                 // first field ignored
 	String1 string `json:"string1"`           // renamed
 	String2 string `json:"-"`                 // ignored
 	String3 string `json:"-,"`                // named "-"
@@ -115,6 +116,7 @@ type TjsontagsString struct {
 }
 
 type TjsontagsBool struct {
+	Bool0 bool `json:"-"`               // first field ignored
 	Bool1 bool `json:"bool1"`           // renamed
 	Bool2 bool `json:"-"`               // ignored
 	Bool3 bool `json:"-,"`              // named "-"
@@ -124,6 +126,7 @@ type TjsontagsBool struct {
 }
 
 type TjsontagsInt struct {
+	Int0 int `json:"-"`              // first field ignored
 	Int1 int `json:"int1"`           // renamed
 	Int2 int `json:"-"`              // ignored
 	Int3 int `json:"-,"`             // named "-"
@@ -133,6 +136,7 @@ type TjsontagsInt struct {
 }
 
 type TjsontagsUint struct {
+	Uint0 int  `json:"-"`               // first field ignored
 	Uint1 uint `json:"uint1"`           // renamed
 	Uint2 uint `json:"-"`               // ignored
 	Uint3 uint `json:"-,"`              // named "-"
@@ -142,6 +146,7 @@ type TjsontagsUint struct {
 }
 
 type TjsontagsFloat struct {
+	Float0 float64 `json:"-"`                // first field ignored
 	Float1 float64 `json:"float1"`           // renamed
 	Float2 float64 `json:"-"`                // ignored
 	Float3 float64 `json:"-,"`               // named "-"
@@ -151,6 +156,7 @@ type TjsontagsFloat struct {
 }
 
 type TjsontagsComplex struct {
+	Complex0 complex128 `json:"-"`                  // first field ignored
 	Complex1 complex128 `json:"complex1"`           // renamed
 	Complex2 complex128 `json:"-"`                  // ignored
 	Complex3 complex128 `json:"-,"`                 // named "-"
@@ -160,6 +166,7 @@ type TjsontagsComplex struct {
 }
 
 type TjsontagsPtr struct {
+	Ptr0 *string `json:"-"`              // first field ignored
 	Ptr1 *string `json:"ptr1"`           // renamed
 	Ptr2 *string `json:"-"`              // ignored
 	Ptr3 *string `json:"-,"`             // named "-"
@@ -169,6 +176,7 @@ type TjsontagsPtr struct {
 }
 
 type TjsontagsArray struct {
+	Array0 [2]string `json:"-"`                // first field ignored
 	Array1 [2]string `json:"array1"`           // renamed
 	Array2 [2]string `json:"-"`                // ignored
 	Array3 [2]string `json:"-,"`               // named "-"
@@ -178,6 +186,7 @@ type TjsontagsArray struct {
 }
 
 type TjsontagsSlice struct {
+	Slice0 []string `json:"-"`                // first field ignored
 	Slice1 []string `json:"slice1"`           // renamed
 	Slice2 []string `json:"-"`                // ignored
 	Slice3 []string `json:"-,"`               // named "-"
@@ -187,6 +196,7 @@ type TjsontagsSlice struct {
 }
 
 type TjsontagsMap struct {
+	Map0 map[string]string `json:"-"`              // first field ignored
 	Map1 map[string]string `json:"map1"`           // renamed
 	Map2 map[string]string `json:"-"`              // ignored
 	Map3 map[string]string `json:"-,"`             // named "-"