Skip to content

Instantly share code, notes, and snippets.

@aktau
Last active October 22, 2026 22:45
Show Gist options
  • Select an option

  • Save aktau/6d191f0feb08825483a39b3d40fb214d to your computer and use it in GitHub Desktop.

Select an option

Save aktau/6d191f0feb08825483a39b3d40fb214d to your computer and use it in GitHub Desktop.
json arshal: typeassert + comma-overwrite
package go852725
import (
"math"
"reflect"
"strconv"
)
// Full TypeAssert + Generics implementation for encoding/json/v2/arshal_default.go.
// Replace *Flags -> *jsonflags.Flags, FormatNilSliceAsNull -> jsonflags.FormatNilSliceAsNull,
// appendQuote -> jsonwire.AppendQuote, and appendFloat -> jsonwire.AppendFloat.
// isSimpleType reports whether values of t can be marshaled by appendSimple.
// This is the case for scalars without custom marshaling and unnamed slices
// of unnamed scalars.
func isSimpleType(t reflect.Type) bool {
if t.Kind() == reflect.Slice {
// Require unnamed slice and unnamed element so reflect.TypeAssert[[]T]
// is guaranteed to match and neither type can have custom marshaling methods.
// A []byte is marshaled as a base64 string, not as a JSON array.
elem := t.Elem()
return t.PkgPath() == "" && elem.PkgPath() == "" &&
elem.Kind() != reflect.Uint8 && isScalarKind(elem.Kind())
}
return isScalarKind(t.Kind()) // in json/v2: && !lookupMarshaler(t).nonDefault
}
// isScalarKind reports whether k is a kind handled by appendScalar.
func isScalarKind(k reflect.Kind) bool {
switch k {
case reflect.Bool, reflect.String,
reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
reflect.Float32, reflect.Float64:
return true
}
return false
}
// appendSimple appends the default JSON representation of v to b,
// where v is a scalar or an unnamed slice of unnamed scalars (see isSimpleType).
// It reports false if v cannot be handled by this fast path,
// in which case the caller must fall back to the regular marshaler.
func appendSimple(b []byte, v reflect.Value, flags *Flags) ([]byte, bool) {
if v.Kind() != reflect.Slice {
return appendScalar(b, v, flags)
}
if v.IsNil() && flags.Get(FormatNilSliceAsNull) {
return append(b, "null"...), true
}
if s, ok := reflect.TypeAssert[[]string](v); ok {
return appendStringSlice(b, s, flags)
}
if s, ok := reflect.TypeAssert[[]int](v); ok {
return appendIntSlice(b, s), true
}
if s, ok := reflect.TypeAssert[[]int64](v); ok {
return appendIntSlice(b, s), true
}
if s, ok := reflect.TypeAssert[[]float64](v); ok {
return appendFloatSlice(b, s, 64)
}
if s, ok := reflect.TypeAssert[[]bool](v); ok {
return appendBoolSlice(b, s), true
}
if s, ok := reflect.TypeAssert[[]int32](v); ok {
return appendIntSlice(b, s), true
}
if s, ok := reflect.TypeAssert[[]uint](v); ok {
return appendUintSlice(b, s), true
}
if s, ok := reflect.TypeAssert[[]uint64](v); ok {
return appendUintSlice(b, s), true
}
if s, ok := reflect.TypeAssert[[]uint32](v); ok {
return appendUintSlice(b, s), true
}
if s, ok := reflect.TypeAssert[[]float32](v); ok {
return appendFloatSlice(b, s, 32)
}
if s, ok := reflect.TypeAssert[[]int16](v); ok {
return appendIntSlice(b, s), true
}
if s, ok := reflect.TypeAssert[[]int8](v); ok {
return appendIntSlice(b, s), true
}
if s, ok := reflect.TypeAssert[[]uint16](v); ok {
return appendUintSlice(b, s), true
}
if s, ok := reflect.TypeAssert[[]uintptr](v); ok {
return appendUintSlice(b, s), true
}
return b, false
}
// appendScalar appends the default JSON representation of a scalar v to b,
// assuming that StringifyNumbers is not set.
// It reports false if v cannot be handled by this fast path
// (e.g., due to non-finite floats or invalid UTF-8),
// in which case the caller must fall back to the regular marshaler.
func appendScalar(b []byte, v reflect.Value, flags *Flags) ([]byte, bool) {
switch v.Kind() {
case reflect.Bool:
return strconv.AppendBool(b, v.Bool()), true
case reflect.String:
b, err := appendQuote(b, []byte(v.String()), flags)
return b, err == nil
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
return strconv.AppendInt(b, v.Int(), 10), true
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
return strconv.AppendUint(b, v.Uint(), 10), true
case reflect.Float32, reflect.Float64:
bits := 64
if v.Kind() == reflect.Float32 {
bits = 32
}
if fv := v.Float(); !math.IsNaN(fv) && !math.IsInf(fv, 0) {
return appendFloat(b, fv, bits), true
}
}
return b, false
}
func appendBoolSlice(b []byte, s []bool) []byte {
if len(s) == 0 {
return append(b, "[]"...)
}
b = append(b, '[')
for _, x := range s {
b = strconv.AppendBool(b, x)
b = append(b, ',')
}
b[len(b)-1] = ']'
return b
}
func appendStringSlice(b []byte, s []string, flags *Flags) ([]byte, bool) {
if len(s) == 0 {
return append(b, "[]"...), true
}
b = append(b, '[')
for _, x := range s {
var err error
if b, err = appendQuote(b, []byte(x), flags); err != nil {
return b, false
}
b = append(b, ',')
}
b[len(b)-1] = ']'
return b, true
}
func appendIntSlice[T ~int | ~int8 | ~int16 | ~int32 | ~int64](b []byte, s []T) []byte {
if len(s) == 0 {
return append(b, "[]"...)
}
b = append(b, '[')
for _, x := range s {
b = strconv.AppendInt(b, int64(x), 10)
b = append(b, ',')
}
b[len(b)-1] = ']'
return b
}
func appendUintSlice[T ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr](b []byte, s []T) []byte {
if len(s) == 0 {
return append(b, "[]"...)
}
b = append(b, '[')
for _, x := range s {
b = strconv.AppendUint(b, uint64(x), 10)
b = append(b, ',')
}
b[len(b)-1] = ']'
return b
}
func appendFloatSlice[T ~float32 | ~float64](b []byte, s []T, bits int) ([]byte, bool) {
if len(s) == 0 {
return append(b, "[]"...), true
}
b = append(b, '[')
for _, x := range s {
fv := float64(x)
if math.IsNaN(fv) || math.IsInf(fv, 0) {
return b, false
}
b = appendFloat(b, fv, bits)
b = append(b, ',')
}
b[len(b)-1] = ']'
return b, true
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment