Repository: bytedance/sonic

Issue:
Compile failed with sonic while enable jsonv2.
**Describe the bug**

Hi there
  I changed to go 1.25 and enabled jsonv2 via set GOEXPERIMENT=jsonv2, upgraded sonic to latest version 1.14.0, there are some compile errors. If change to "encoding/json" and disable jsonv2, then it build successful. Can you please take a look at this? thank you.

```
package main

import (
	"encoding/json/v2"
	"fmt"
	"time"

	"github.com/bytedance/sonic"
)

// JSONTestData represents test data structure for JSON processing
type JSONTestData struct {
	ID        int64   `json:"id"`
	Name      string  `json:"name"`
	Value     float64 `json:"value"`
	Timestamp int64   `json:"timestamp"`
}

func main() {
	// Create test messages using standard JSON
	testMessages := JSONTestData{
		ID:        1001,
		Name:      "kafka_test_message",
		Value:     123.45,
		Timestamp: time.Now().Unix(),
	}

	msg, err := json.Marshal(testMessages)
	if err != nil {
		fmt.Printf("Failed to marshal testMessages: %v", err)
		return
	}
	fmt.Printf("Test json message: %s\n", msg)

	sonicMsg, err := sonic.Marshal(testMessages)
	if err != nil {
		fmt.Printf("Failed to marshal testMessages with Sonic: %v", err)
		return
	}
	fmt.Printf("Test sonic message: %s\n", sonicMsg)
}

```
error output:
```
go build

github.com/bytedance/sonic/internal/resolver.resolveFields: relocation target encoding/json.typeFields not defined
github.com/bytedance/sonic/internal/encoder/vm.Execute: relocation target encoding/json.isValidNumber not defined
github.com/bytedance/sonic/internal/rt.IsValidNumber·f: relocation target encoding/json.isValidNumber not defined

```


**Sonic version:**
v1.14.0

**Environment:**
Windows 10

go 1.25
set GOEXPERIMENT=jsonv2


Discussion:
@AsterDY: Thx, we will fix it@rts-gordon: hi @AsterDY 
  
May I know when will release the next version and fix this issue? Thank you.

Solution patch:
diff --git a/.github/workflows/compatibility_test-windows.yml b/.github/workflows/compatibility_test-windows.yml
index ad8b61e..d0caac5 100644
--- a/.github/workflows/compatibility_test-windows.yml
+++ b/.github/workflows/compatibility_test-windows.yml
@@ -6,7 +6,7 @@ jobs:
   build:
     strategy:
       matrix:
-        go-version: [1.17.x, 1.22.x, 1.23.x]
+        go-version: [1.18.x, 1.21.x, 1.25.x]
     runs-on: windows-latest
     steps:
       - uses: actions/checkout@v2
diff --git a/.github/workflows/compatibility_test.yml b/.github/workflows/compatibility_test.yml
index cc6dfbd..78a68a7 100644
--- a/.github/workflows/compatibility_test.yml
+++ b/.github/workflows/compatibility_test.yml
@@ -6,7 +6,7 @@ jobs:
   build:
     strategy:
       matrix:
-        go-version: [1.17.x, 1.18.x, 1.19.x, 1.20.x, 1.21.x, 1.22.x, 1.23.x]
+        go-version: [1.18.x, 1.19.x, 1.20.x, 1.21.x, 1.22.x, 1.23.x, 1.24.x, 1.25.x]
         os: [ubuntu-latest, ubuntu-24.04-arm]
     runs-on: ${{ matrix.os }}
     steps:
diff --git a/.github/workflows/test-arm64.yml b/.github/workflows/test-arm64.yml
index 67b5f7f..1f38ceb 100644
--- a/.github/workflows/test-arm64.yml
+++ b/.github/workflows/test-arm64.yml
@@ -7,7 +7,7 @@ jobs:
   build:
     strategy:
       matrix:
-        go-version: [1.20.x, 1.21.x, 1.22.x, 1.23.x, 1.24.x]
+        go-version: [1.20.x, 1.22.x, 1.25.x]
         runner_arch: [ubuntu-24.04-arm]
 
     runs-on: ${{ matrix.runner_arch }}
diff --git a/.github/workflows/test-x86.yml b/.github/workflows/test-x86.yml
index 0788f3b..21f3c1c 100644
--- a/.github/workflows/test-x86.yml
+++ b/.github/workflows/test-x86.yml
@@ -7,7 +7,7 @@ jobs:
   build:
     strategy:
       matrix:
-        go-version: [1.18.x, 1.19.x, 1.20.x, 1.21.x, 1.22.x, 1.23.x, 1.24.x]
+        go-version: [1.18.x, 1.21.x, 1.25.x]
         runner_arch: [ubuntu-latest]
 
     runs-on: ${{ matrix.runner_arch }}
diff --git a/README.md b/README.md
index 41fe776..6ada7f6 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ A blazingly fast JSON serializing &amp; deserializing library, accelerated by JI
 
 ## Requirement
 
-- Go: 1.17~1.24
+- Go: 1.18~1.25
   - Notice: Go1.24.0 is not supported due to the [issue](https://github.com/golang/go/issues/71672), please use higher go version or add build tag `--ldflags="-checklinkname=0"` 
 - OS: Linux / MacOS / Windows
 - CPU: AMD64 / (ARM64, need go1.20 above)
diff --git a/README_ZH_CN.md b/README_ZH_CN.md
index 3c24a51..ef4fc21 100644
--- a/README_ZH_CN.md
+++ b/README_ZH_CN.md
@@ -6,7 +6,7 @@
 
 ## 依赖
 
-- Go: 1.17~1.24
+- Go: 1.18~1.25
   - 注意：Go1.24.0 由于 [issue](https://github.com/golang/go/issues/71672) 不可用，请升级到更高 Go 版本，或添加编译选项 `--ldflags="-checklinkname=0"` 
 - OS: Linux / MacOS / Windows
 - CPU: AMD64 / (ARM64, 需要 Go1.20 以上）
diff --git a/fuzz/go.mod b/fuzz/go.mod
index 19ecb0e..16ec852 100644
--- a/fuzz/go.mod
+++ b/fuzz/go.mod
@@ -3,19 +3,20 @@ module github.com/bytedance/sonic/fuzz
 go 1.18
 
 require (
-	github.com/bytedance/gopkg v0.0.0-20221122125632-68358b8ecec6
+	github.com/bytedance/gopkg v0.1.3
 	github.com/bytedance/sonic v1.11.5-alpha3
 	github.com/davecgh/go-spew v1.1.1
-	github.com/stretchr/testify v1.8.1
+	github.com/stretchr/testify v1.10.0
 )
 
 require (
 	github.com/bytedance/sonic/loader v0.3.0 // indirect
-	github.com/cloudwego/base64x v0.1.5 // indirect
-	github.com/klauspost/cpuid/v2 v2.0.9 // indirect
+	github.com/cloudwego/base64x v0.1.6 // indirect
+	github.com/klauspost/cpuid/v2 v2.2.9 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
 	golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect
+	golang.org/x/sys v0.22.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
 )
 
diff --git a/fuzz/go.sum b/fuzz/go.sum
index c75b68c..904da71 100644
--- a/fuzz/go.sum
+++ b/fuzz/go.sum
@@ -1,36 +1,27 @@
-github.com/bytedance/gopkg v0.0.0-20221122125632-68358b8ecec6 h1:FCLDGi1EmB7JzjVVYNZiqc/zAJj2BQ5M0lfkVOxbfs8=
-github.com/bytedance/gopkg v0.0.0-20221122125632-68358b8ecec6/go.mod h1:5FoAH5xUHHCMDvQPy1rnj8moqLkLHFaDVBjHhcFwEi0=
-github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
+github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M=
 github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA=
 github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI=
-github.com/cloudwego/base64x v0.1.5 h1:XPciSp1xaq2VCSt6lF0phncD4koWyULpl5bUxbfCyP4=
-github.com/cloudwego/base64x v0.1.5/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
-github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
+github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M=
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4=
-github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
-github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
+github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
 github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
 github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
 golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
 golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
diff --git a/go.mod b/go.mod
index 2816aa7..91a16dd 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module github.com/bytedance/sonic
 
-go 1.17
+go 1.18
 
 require (
 	github.com/bytedance/gopkg v0.1.3
@@ -8,7 +8,7 @@ require (
 	github.com/cloudwego/base64x v0.1.6
 	github.com/davecgh/go-spew v1.1.1
 	github.com/klauspost/cpuid/v2 v2.2.9
-	github.com/stretchr/testify v1.9.0
+	github.com/stretchr/testify v1.10.0
 	github.com/twitchyliquid64/golang-asm v0.15.1
 	golang.org/x/arch v0.0.0-20210923205945-b76863e36670
 )
diff --git a/go.sum b/go.sum
index 7b2614c..d06bf3d 100644
--- a/go.sum
+++ b/go.sum
@@ -14,66 +14,19 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
-github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
-github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
+github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
 github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
-github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
 golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
-golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
-golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
-golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
-golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
-golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
-golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
 golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
-golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
-golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
-golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
-golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
-golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
diff --git a/go.work b/go.work
index 7cac2c2..34c9906 100644
--- a/go.work
+++ b/go.work
@@ -5,6 +5,6 @@ use (
 	./external_jsonlib_test
 	./fuzz
 	./generic_test
-	./loader
 	./issue_test
+	./loader
 )
diff --git a/internal/encoder/alg/mapiter.go b/internal/encoder/alg/mapiter.go
index d700b10..4664d90 100644
--- a/internal/encoder/alg/mapiter.go
+++ b/internal/encoder/alg/mapiter.go
@@ -224,3 +224,62 @@ func asText(v unsafe.Pointer) (string, error) {
 	r, e := (*(*encoding.TextMarshaler)(unsafe.Pointer(&text))).MarshalText()
 	return rt.Mem2Str(r), e
 }
+
+func IsValidNumber(s string) bool {
+	// This function implements the JSON numbers grammar.
+	// See https://tools.ietf.org/html/rfc7159#section-6
+	// and https://www.json.org/img/number.png
+
+	if s == "" {
+		return false
+	}
+
+	// Optional -
+	if s[0] == '-' {
+		s = s[1:]
+		if s == "" {
+			return false
+		}
+	}
+
+	// Digits
+	switch {
+	default:
+		return false
+
+	case s[0] == '0':
+		s = s[1:]
+
+	case '1' <= s[0] && s[0] <= '9':
+		s = s[1:]
+		for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
+			s = s[1:]
+		}
+	}
+
+	// . followed by 1 or more digits.
+	if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
+		s = s[2:]
+		for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
+			s = s[1:]
+		}
+	}
+
+	// e or E followed by an optional - or + and
+	// 1 or more digits.
+	if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
+		s = s[1:]
+		if s[0] == '+' || s[0] == '-' {
+			s = s[1:]
+			if s == "" {
+				return false
+			}
+		}
+		for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
+			s = s[1:]
+		}
+	}
+
+	// Make sure we are at the end.
+	return s == ""
+}
diff --git a/internal/encoder/alg/primitives.go b/internal/encoder/prim/primitives.go
similarity index 89%
rename from internal/encoder/alg/primitives.go
rename to internal/encoder/prim/primitives.go
index e2610fb..ec4d2f5 100644
--- a/internal/encoder/alg/primitives.go
+++ b/internal/encoder/prim/primitives.go
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package alg
+package prim
 
 import (
 	"encoding"
@@ -22,6 +22,7 @@ import (
 	"reflect"
 	"unsafe"
 
+	"github.com/bytedance/sonic/internal/encoder/alg"
 	"github.com/bytedance/sonic/internal/encoder/vars"
 	"github.com/bytedance/sonic/internal/resolver"
 	"github.com/bytedance/sonic/internal/rt"
@@ -70,11 +71,11 @@ func EncodeJsonMarshaler(buf *[]byte, val json.Marshaler, opt uint64) error {
 	if ret, err := val.MarshalJSON(); err != nil {
 		return err
 	} else {
-		if opt&(1<<BitCompactMarshaler) != 0 {
+		if opt&(1<<alg.BitCompactMarshaler) != 0 {
 			return Compact(buf, ret)
 		}
-		if opt&(1<<BitNoValidateJSONMarshaler) == 0 {
-			if ok, s := Valid(ret); !ok {
+		if opt&(1<<alg.BitNoValidateJSONMarshaler) == 0 {
+			if ok, s := alg.Valid(ret); !ok {
 				return vars.Error_marshaler(ret, s)
 			}
 		}
@@ -87,11 +88,11 @@ func EncodeTextMarshaler(buf *[]byte, val encoding.TextMarshaler, opt uint64) er
 	if ret, err := val.MarshalText(); err != nil {
 		return err
 	} else {
-		if opt&(1<<BitNoQuoteTextMarshaler) != 0 {
+		if opt&(1<<alg.BitNoQuoteTextMarshaler) != 0 {
 			*buf = append(*buf, ret...)
 			return nil
 		}
-		*buf = Quote(*buf, rt.Mem2Str(ret), false)
+		*buf = alg.Quote(*buf, rt.Mem2Str(ret), false)
 		return nil
 	}
 }
diff --git a/internal/encoder/vm/stbus.go b/internal/encoder/vm/stbus.go
index 21b476c..152c72c 100644
--- a/internal/encoder/vm/stbus.go
+++ b/internal/encoder/vm/stbus.go
@@ -22,13 +22,14 @@ import (
 
 	"github.com/bytedance/sonic/internal/encoder/alg"
 	"github.com/bytedance/sonic/internal/encoder/ir"
+	"github.com/bytedance/sonic/internal/encoder/prim"
 	"github.com/bytedance/sonic/internal/encoder/vars"
 	"github.com/bytedance/sonic/internal/rt"
 )
 
 func EncodeTypedPointer(buf *[]byte, vt *rt.GoType, vp *unsafe.Pointer, sb *vars.Stack, fv uint64) error {
 	if vt == nil {
-		return alg.EncodeNil(buf)
+		return prim.EncodeNil(buf)
 	} else if pp, err := vars.FindOrCompile(vt, (fv&(1<<alg.BitPointerValue)) != 0, compiler); err != nil {
 		return err
 	} else if vt.Indirect() {
diff --git a/internal/encoder/vm/vm.go b/internal/encoder/vm/vm.go
index aa3f515..93426b9 100644
--- a/internal/encoder/vm/vm.go
+++ b/internal/encoder/vm/vm.go
@@ -24,6 +24,7 @@ import (
 
 	"github.com/bytedance/sonic/internal/encoder/alg"
 	"github.com/bytedance/sonic/internal/encoder/ir"
+	"github.com/bytedance/sonic/internal/encoder/prim"
 	"github.com/bytedance/sonic/internal/encoder/vars"
 	"github.com/bytedance/sonic/internal/rt"
 )
@@ -183,7 +184,7 @@ func Execute(b *[]byte, p unsafe.Pointer, s *vars.Stack, flags uint64, prog *ir.
 			v := *(*json.Number)(p)
 			if v == "" {
 				buf = append(buf, '0')
-			} else if !rt.IsValidNumber(string(v)) {
+			} else if !alg.IsValidNumber(string(v)) {
 				return vars.Error_number(v)
 			} else {
 				buf = append(buf, v...)
@@ -242,13 +243,13 @@ func Execute(b *[]byte, p unsafe.Pointer, s *vars.Stack, flags uint64, prog *ir.
 				case reflect.Ptr, reflect.Map : it = convT2I(p, true, itab)
 				default                       : it = convT2I(p, !vt.Indirect(), itab)
 			}
-			if err := alg.EncodeTextMarshaler(&buf, *(*encoding.TextMarshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
+			if err := prim.EncodeTextMarshaler(&buf, *(*encoding.TextMarshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
 				return err
 			}
 		case ir.OP_marshal_text_p:
 			_, itab := ins.Vtab()
 			it := convT2I(p, false, itab)
-			if err := alg.EncodeTextMarshaler(&buf, *(*encoding.TextMarshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
+			if err := prim.EncodeTextMarshaler(&buf, *(*encoding.TextMarshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
 				return err
 			}
 		case ir.OP_map_write_key:
@@ -285,7 +286,7 @@ func Execute(b *[]byte, p unsafe.Pointer, s *vars.Stack, flags uint64, prog *ir.
 			}
 		case ir.OP_is_zero:
 			fv := ins.VField()
-			if alg.IsZero(p, fv) {
+			if prim.IsZero(p, fv) {
 				pc = ins.Vi()
 				continue
 			}
@@ -334,13 +335,13 @@ func Execute(b *[]byte, p unsafe.Pointer, s *vars.Stack, flags uint64, prog *ir.
 				case reflect.Ptr, reflect.Map : it = convT2I(p, true, itab)
 				default                       : it = convT2I(p, !vt.Indirect(), itab)
 			}
-			if err := alg.EncodeJsonMarshaler(&buf, *(*json.Marshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
+			if err := prim.EncodeJsonMarshaler(&buf, *(*json.Marshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
 				return err
 			}
 		case ir.OP_marshal_p:
 			_, itab := ins.Vtab()
 			it := convT2I(p, false, itab)
-			if err := alg.EncodeJsonMarshaler(&buf, *(*json.Marshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
+			if err := prim.EncodeJsonMarshaler(&buf, *(*json.Marshaler)(unsafe.Pointer(&it)), (flags)); err != nil {
 				return err
 			}
 		case ir.OP_unsupported:
diff --git a/internal/encoder/x86/assembler_regabi_amd64.go b/internal/encoder/x86/assembler_regabi_amd64.go
index 927c436..f86fa56 100644
--- a/internal/encoder/x86/assembler_regabi_amd64.go
+++ b/internal/encoder/x86/assembler_regabi_amd64.go
@@ -28,6 +28,7 @@ import (
 	"github.com/bytedance/sonic/internal/cpu"
 	"github.com/bytedance/sonic/internal/encoder/alg"
 	"github.com/bytedance/sonic/internal/encoder/ir"
+	"github.com/bytedance/sonic/internal/encoder/prim"
 	"github.com/bytedance/sonic/internal/encoder/vars"
 	"github.com/bytedance/sonic/internal/jit"
 	"github.com/bytedance/sonic/internal/native/types"
@@ -764,7 +765,7 @@ var (
 var (
 	_F_memmove       = jit.Func(rt.Memmove)
 	_F_error_number  = jit.Func(vars.Error_number)
-	_F_isValidNumber = jit.Func(rt.IsValidNumber)
+	_F_isValidNumber = jit.Func(alg.IsValidNumber)
 )
 
 var (
@@ -784,8 +785,8 @@ const (
 )
 
 func init() {
-	_F_encodeJsonMarshaler = jit.Func(alg.EncodeJsonMarshaler)
-	_F_encodeTextMarshaler = jit.Func(alg.EncodeTextMarshaler)
+	_F_encodeJsonMarshaler = jit.Func(prim.EncodeJsonMarshaler)
+	_F_encodeTextMarshaler = jit.Func(prim.EncodeTextMarshaler)
 	_F_encodeTypedPointer  = jit.Func(EncodeTypedPointer)
 }
 
@@ -1100,7 +1101,7 @@ func (self *Assembler) _asm_OP_is_zero_map(p *ir.Instr) {
 }
 
 var (
-	_F_is_zero = jit.Func(alg.IsZero)
+	_F_is_zero = jit.Func(prim.IsZero)
 	_T_reflect_Type = rt.UnpackIface(reflect.Type(nil))
 )
 
diff --git a/internal/encoder/x86/stbus.go b/internal/encoder/x86/stbus.go
index 7b6b1f9..45bb972 100644
--- a/internal/encoder/x86/stbus.go
+++ b/internal/encoder/x86/stbus.go
@@ -21,6 +21,7 @@ import (
 	_ "unsafe"
 
 	"github.com/bytedance/sonic/internal/encoder/alg"
+	"github.com/bytedance/sonic/internal/encoder/prim"
 	"github.com/bytedance/sonic/internal/encoder/vars"
 	"github.com/bytedance/sonic/internal/rt"
 	"github.com/bytedance/sonic/loader"
@@ -39,7 +40,7 @@ func ptoenc(p loader.Function) vars.Encoder {
 
 func EncodeTypedPointer(buf *[]byte, vt *rt.GoType, vp *unsafe.Pointer, sb *vars.Stack, fv uint64) error {
 	if vt == nil {
-		return alg.EncodeNil(buf)
+		return prim.EncodeNil(buf)
 	} else if fn, err := vars.FindOrCompile(vt, (fv&(1<<alg.BitPointerValue)) != 0, compiler); err != nil {
 		return err
 	} else if vt.Indirect() {
diff --git a/internal/resolver/fields.go b/internal/resolver/fields.go
new file mode 100644
index 0000000..614bef4
--- /dev/null
+++ b/internal/resolver/fields.go
@@ -0,0 +1,388 @@
+/**
+ * Copyright 2025 ByteDance Inc.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package resolver
+
+import (
+	"reflect"
+	"sort"
+	"strings"
+	"unicode"
+	"unicode/utf8"
+
+	"github.com/bytedance/sonic/internal/encoder/alg"
+)
+
+type StdField struct {
+    name        string
+    nameBytes   []byte
+    nameNonEsc  string
+    nameEscHTML string
+    tag         bool
+    index       []int
+    typ         reflect.Type
+    omitEmpty   bool
+    omitZero    bool
+    isZero      func(reflect.Value) bool
+    quoted      bool
+}
+
+type StdStructFields struct {
+    list      []StdField
+    nameIndex map[string]*StdField
+    byFoldedName map[string]*StdField
+}
+
+func typeFields(t reflect.Type) StdStructFields {
+	// Anonymous fields to explore at the current level and the next.
+	current := []StdField{}
+	next := []StdField{{typ: t}}
+
+	// Count of queued names for current level and the next.
+	var count, nextCount map[reflect.Type]int
+
+	// Types already visited at an earlier level.
+	visited := map[reflect.Type]bool{}
+
+	// Fields found.
+	var fields []StdField
+
+	// Buffer to run appendHTMLEscape on field names.
+	var nameEscBuf []byte
+
+	for len(next) > 0 {
+		current, next = next, current[:0]
+		count, nextCount = nextCount, map[reflect.Type]int{}
+
+		for _, f := range current {
+			if visited[f.typ] {
+				continue
+			}
+			visited[f.typ] = true
+
+			// Scan f.typ for fields to include.
+			for i := 0; i < f.typ.NumField(); i++ {
+				sf := f.typ.Field(i)
+				if sf.Anonymous {
+					t := sf.Type
+					if t.Kind() == reflect.Pointer {
+						t = t.Elem()
+					}
+					if !sf.IsExported() && t.Kind() != reflect.Struct {
+						// Ignore embedded fields of unexported non-struct types.
+						continue
+					}
+					// Do not ignore embedded fields of unexported struct types
+					// since they may have exported fields.
+				} else if !sf.IsExported() {
+					// Ignore unexported non-embedded fields.
+					continue
+				}
+				tag := sf.Tag.Get("json")
+				if tag == "-" {
+					continue
+				}
+				name, opts := parseTag(tag)
+				if !isValidTag(name) {
+					name = ""
+				}
+				index := make([]int, len(f.index)+1)
+				copy(index, f.index)
+				index[len(f.index)] = i
+
+				ft := sf.Type
+				if ft.Name() == "" && ft.Kind() == reflect.Pointer {
+					// Follow pointer.
+					ft = ft.Elem()
+				}
+
+				// Only strings, floats, integers, and booleans can be quoted.
+				quoted := false
+				if opts.Contains("string") {
+					switch ft.Kind() {
+					case reflect.Bool,
+						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,
+						reflect.String:
+						quoted = true
+					}
+				}
+
+				// Record found field and index sequence.
+				if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
+					tagged := name != ""
+					if name == "" {
+						name = sf.Name
+					}
+					field := StdField{
+						name:      name,
+						tag:       tagged,
+						index:     index,
+						typ:       ft,
+						omitEmpty: opts.Contains("omitempty"),
+						omitZero:  opts.Contains("omitzero"),
+						quoted:    quoted,
+					}
+					field.nameBytes = []byte(field.name)
+
+					// Build nameEscHTML and nameNonEsc ahead of time.
+					nameEscBuf = alg.HtmlEscape(nameEscBuf[:0], field.nameBytes)
+					field.nameEscHTML = `"` + string(nameEscBuf) + `":`
+					field.nameNonEsc = `"` + field.name + `":`
+
+					if field.omitZero {
+						t := sf.Type
+						// Provide a function that uses a type's IsZero method.
+						switch {
+						case t.Kind() == reflect.Interface && t.Implements(isZeroerType):
+							field.isZero = func(v reflect.Value) bool {
+								// Avoid panics calling IsZero on a nil interface or
+								// non-nil interface with nil pointer.
+								return v.IsNil() ||
+									(v.Elem().Kind() == reflect.Pointer && v.Elem().IsNil()) ||
+									v.Interface().(isZeroer).IsZero()
+							}
+						case t.Kind() == reflect.Pointer && t.Implements(isZeroerType):
+							field.isZero = func(v reflect.Value) bool {
+								// Avoid panics calling IsZero on nil pointer.
+								return v.IsNil() || v.Interface().(isZeroer).IsZero()
+							}
+						case t.Implements(isZeroerType):
+							field.isZero = func(v reflect.Value) bool {
+								return v.Interface().(isZeroer).IsZero()
+							}
+						case reflect.PointerTo(t).Implements(isZeroerType):
+							field.isZero = func(v reflect.Value) bool {
+								if !v.CanAddr() {
+									// Temporarily box v so we can take the address.
+									v2 := reflect.New(v.Type()).Elem()
+									v2.Set(v)
+									v = v2
+								}
+								return v.Addr().Interface().(isZeroer).IsZero()
+							}
+						}
+					}
+
+					fields = append(fields, field)
+					if count[f.typ] > 1 {
+						// If there were multiple instances, add a second,
+						// so that the annihilation code will see a duplicate.
+						// It only cares about the distinction between 1 and 2,
+						// so don't bother generating any more copies.
+						fields = append(fields, fields[len(fields)-1])
+					}
+					continue
+				}
+
+				// Record new anonymous struct to explore in next round.
+				nextCount[ft]++
+				if nextCount[ft] == 1 {
+					next = append(next, StdField{name: ft.Name(), index: index, typ: ft})
+				}
+			}
+		}
+	}
+
+	sort.Slice(fields, func(i, j int) bool {
+		a, b := fields[i], fields[j]
+		// sort field by name, breaking ties with depth, then
+		// breaking ties with "name came from json tag", then
+		// breaking ties with index sequence.
+		if c := strings.Compare(a.name, b.name); c != 0 {
+			return c < 0
+		}
+		if len(a.index) != len(b.index) {
+			return len(a.index) < len(b.index)
+		}
+		if a.tag != b.tag {
+			if a.tag {
+				return true
+			}
+			return false
+		}
+		return compare(a.index, b.index) < 0
+	})
+
+	// Delete all fields that are hidden by the Go rules for embedded fields,
+	// except that fields with JSON tags are promoted.
+
+	// The fields are sorted in primary order of name, secondary order
+	// of field index length. Loop over names; for each name, delete
+	// hidden fields by choosing the one dominant field that survives.
+	out := fields[:0]
+	for advance, i := 0, 0; i < len(fields); i += advance {
+		// One iteration per name.
+		// Find the sequence of fields with the name of this first field.
+		fi := fields[i]
+		name := fi.name
+		for advance = 1; i+advance < len(fields); advance++ {
+			fj := fields[i+advance]
+			if fj.name != name {
+				break
+			}
+		}
+		if advance == 1 { // Only one field with this name
+			out = append(out, fi)
+			continue
+		}
+		dominant, ok := dominantField(fields[i : i+advance])
+		if ok {
+			out = append(out, dominant)
+		}
+	}
+
+	fields = out
+	sort.Slice(fields, func(i, j int) bool {
+		a, b := fields[i], fields[j]
+		return compare(a.index, b.index) < 0
+	})
+
+	exactNameIndex := make(map[string]*StdField, len(fields))
+	foldedNameIndex := make(map[string]*StdField, len(fields))
+	for i, field := range fields {
+		exactNameIndex[field.name] = &fields[i]
+		// For historical reasons, first folded match takes precedence.
+		if _, ok := foldedNameIndex[string(foldName(field.nameBytes))]; !ok {
+			foldedNameIndex[string(foldName(field.nameBytes))] = &fields[i]
+		}
+	}
+	return StdStructFields{fields, exactNameIndex, foldedNameIndex}
+}
+
+func compare(s1, s2 []int) int {
+	for i, v1 := range s1 {
+		if i >= len(s2) {
+			return +1
+		}
+		v2 := s2[i]
+		if v1 != v2 {
+			return v1 - v2
+		}
+	}
+	if len(s1) < len(s2) {
+		return -1
+	}
+	return 0
+}
+
+type isZeroer interface {
+	IsZero() bool
+}
+
+var isZeroerType = reflect.TypeOf((*isZeroer)(nil)).Elem()
+
+// tagOptions is the string following a comma in a struct field's "json"
+// tag, or the empty string. It does not include the leading comma.
+type tagOptions string
+
+// parseTag splits a struct field's json tag into its name and
+// comma-separated options.
+func parseTag(tag string) (string, tagOptions) {
+	tag, opt, _ := strings.Cut(tag, ",")
+	return tag, tagOptions(opt)
+}
+
+// Contains reports whether a comma-separated list of options
+// contains a particular substr flag. substr must be surrounded by a
+// string boundary or commas.
+func (o tagOptions) Contains(optionName string) bool {
+	if len(o) == 0 {
+		return false
+	}
+	s := string(o)
+	for s != "" {
+		var name string
+		name, s, _ = strings.Cut(s, ",")
+		if name == optionName {
+			return true
+		}
+	}
+	return false
+}
+
+func isValidTag(s string) bool {
+	if s == "" {
+		return false
+	}
+	for _, c := range s {
+		switch {
+		case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c):
+			// Backslash and quote chars are reserved, but
+			// otherwise any punctuation chars are allowed
+			// in a tag name.
+		case !unicode.IsLetter(c) && !unicode.IsDigit(c):
+			return false
+		}
+	}
+	return true
+}
+
+// dominantField looks through the fields, all of which are known to
+// have the same name, to find the single field that dominates the
+// others using Go's embedding rules, modified by the presence of
+// JSON tags. If there are multiple top-level fields, the boolean
+// will be false: This condition is an error in Go and we skip all
+// the fields.
+func dominantField(fields []StdField) (StdField, bool) {
+	// The fields are sorted in increasing index-length order, then by presence of tag.
+	// That means that the first field is the dominant one. We need only check
+	// for error cases: two fields at top level, either both tagged or neither tagged.
+	if len(fields) > 1 && len(fields[0].index) == len(fields[1].index) && fields[0].tag == fields[1].tag {
+		return StdField{}, false
+	}
+	return fields[0], true
+}
+
+
+// foldName returns a folded string such that foldName(x) == foldName(y)
+// is identical to bytes.EqualFold(x, y).
+func foldName(in []byte) []byte {
+	// This is inlinable to take advantage of "function outlining".
+	var arr [32]byte // large enough for most JSON names
+	return appendFoldedName(arr[:0], in)
+}
+
+func appendFoldedName(out, in []byte) []byte {
+	for i := 0; i < len(in); {
+		// Handle single-byte ASCII.
+		if c := in[i]; c < utf8.RuneSelf {
+			if 'a' <= c && c <= 'z' {
+				c -= 'a' - 'A'
+			}
+			out = append(out, c)
+			i++
+			continue
+		}
+		// Handle multi-byte Unicode.
+		r, n := utf8.DecodeRune(in[i:])
+		out = utf8.AppendRune(out, foldRune(r))
+		i += n
+	}
+	return out
+}
+
+// foldRune is returns the smallest rune for all runes in the same fold set.
+func foldRune(r rune) rune {
+	for {
+		r2 := unicode.SimpleFold(r)
+		if r2 <= r {
+			return r2
+		}
+		r = r2
+	}
+}
diff --git a/internal/resolver/resolver.go b/internal/resolver/resolver.go
index 1c30ad1..4303c67 100644
--- a/internal/resolver/resolver.go
+++ b/internal/resolver/resolver.go
@@ -21,6 +21,7 @@ import (
 	"reflect"
 	"strings"
 	"sync"
+    _ "unsafe"
 )
 
 type FieldOpts int
@@ -216,3 +217,10 @@ func ResolveStruct(vt reflect.Type) []FieldMeta {
     fieldCache[vt] = fm
     return fm
 }
+
+func handleOmitZero(fv StdField, fm *FieldMeta) {
+    if fv.omitZero {
+        fm.Opts |= F_omitzero
+        fm.IsZero = fv.isZero
+    }
+}
diff --git a/internal/resolver/stubs_go120.go b/internal/resolver/stubs_go120.go
deleted file mode 100644
index c0276f5..0000000
--- a/internal/resolver/stubs_go120.go
+++ /dev/null
@@ -1,51 +0,0 @@
-//go:build !go1.21
-// +build !go1.21
-
-/*
- * Copyright 2021 ByteDance Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package resolver
-
-import (
-    _ `encoding/json`
-    `reflect`
-    _ `unsafe`
-)
-
-type StdField struct {
-    name        string
-    nameBytes   []byte
-    equalFold   func()
-    nameNonEsc  string
-    nameEscHTML string
-    tag         bool
-    index       []int
-    typ         reflect.Type
-    omitEmpty   bool
-    quoted      bool
-    encoder     func()
-}
-
-type StdStructFields struct {
-    list      []StdField
-    nameIndex map[string]int
-}
-
-//go:noescape
-//go:linkname typeFields encoding/json.typeFields
-func typeFields(_ reflect.Type) StdStructFields
-
-func handleOmitZero(f StdField, fv *FieldMeta) {}
diff --git a/internal/resolver/stubs_go123.go b/internal/resolver/stubs_go123.go
deleted file mode 100644
index a73f024..0000000
--- a/internal/resolver/stubs_go123.go
+++ /dev/null
@@ -1,51 +0,0 @@
-//go:build go1.21 && !go1.24
-// +build go1.21,!go1.24
-
-/*
- * Copyright 2021 ByteDance Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package resolver
-
-import (
-    _ `encoding/json`
-    `reflect`
-    _ `unsafe`
-)
-
-type StdField struct {
-    name        string
-    nameBytes   []byte
-    nameNonEsc  string
-    nameEscHTML string
-    tag         bool
-    index       []int
-    typ         reflect.Type
-    omitEmpty   bool
-    quoted      bool
-    encoder     func()
-}
-
-type StdStructFields struct {
-    list      []StdField
-    nameIndex map[string]*StdField
-    byFoldedName map[string]*StdField
-}
-
-//go:noescape
-//go:linkname typeFields encoding/json.typeFields
-func typeFields(_ reflect.Type) StdStructFields
-
-func handleOmitZero(f StdField, fv *FieldMeta) {}
diff --git a/internal/rt/stubs.go b/internal/rt/stubs.go
index f692f15..553f0f9 100644
--- a/internal/rt/stubs.go
+++ b/internal/rt/stubs.go
@@ -38,9 +38,6 @@ func Mapiterinit(t *GoMapType, m unsafe.Pointer, it *GoMapIterator)
 //go:linkname Maplen reflect.maplen
 func Maplen(h unsafe.Pointer) int 
 
-//go:linkname IsValidNumber encoding/json.isValidNumber
-func IsValidNumber(s string) bool
-
 //go:nosplit
 //go:linkname MemclrHasPointers runtime.memclrHasPointers
 //goland:noinspection GoUnusedParameter
diff --git a/loader/go.mod b/loader/go.mod
index 1d334f5..c951cb6 100644
--- a/loader/go.mod
+++ b/loader/go.mod
@@ -4,5 +4,5 @@ go 1.16
 
 require (
 	github.com/davecgh/go-spew v1.1.1
-	github.com/stretchr/testify v1.8.1
+	github.com/stretchr/testify v1.10.0
 )
diff --git a/loader/go.sum b/loader/go.sum
index 2ec90f7..177bd1a 100644
--- a/loader/go.sum
+++ b/loader/go.sum
@@ -8,8 +8,8 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
 github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
-github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=



Test patch:
diff --git a/external_jsonlib_test/go.mod b/external_jsonlib_test/go.mod
index d71d28d..0fc38f2 100644
--- a/external_jsonlib_test/go.mod
+++ b/external_jsonlib_test/go.mod
@@ -7,7 +7,7 @@ require (
 	github.com/bytedance/sonic v1.11.5-alpha3
 	github.com/goccy/go-json v0.9.11
 	github.com/json-iterator/go v1.1.12
-	github.com/stretchr/testify v1.9.0
+	github.com/stretchr/testify v1.10.0
 	github.com/tidwall/gjson v1.14.3
 	github.com/tidwall/sjson v1.2.5
 	github.com/valyala/fastjson v1.6.4
diff --git a/external_jsonlib_test/go.sum b/external_jsonlib_test/go.sum
index 519b1ea..c4df6d3 100644
--- a/external_jsonlib_test/go.sum
+++ b/external_jsonlib_test/go.sum
@@ -29,8 +29,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
-github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
 github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
 github.com/tidwall/gjson v1.14.3 h1:9jvXn7olKEHU1S9vwoMGliaT8jq1vJ7IH/n9zD9Dnlw=
 github.com/tidwall/gjson v1.14.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
diff --git a/generic_test/go.sum b/generic_test/go.sum
index a414b1d..0076bff 100644
--- a/generic_test/go.sum
+++ b/generic_test/go.sum
@@ -29,7 +29,7 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
 github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
+github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
 github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
 github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
 golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU=
diff --git a/internal/resolver/stubs_latest.go b/internal/resolver/stubs_latest.go
deleted file mode 100644
index b9486a6..0000000
--- a/internal/resolver/stubs_latest.go
+++ /dev/null
@@ -1,59 +0,0 @@
-//go:build go1.24
-// +build go1.24
-
-/*
- * Copyright 2021 ByteDance Inc.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package resolver
-
-import (
-    _ `encoding/json`
-    `reflect`
-    _ `unsafe`
-)
-
-type StdField struct {
-    name        string
-    nameBytes   []byte
-    nameNonEsc  string
-    nameEscHTML string
-    tag         bool
-    index       []int
-    typ         reflect.Type
-    omitEmpty   bool
-    omitZero    bool
-    isZero      func(reflect.Value) bool
-    quoted      bool
-    encoder     func()
-}
-
-type StdStructFields struct {
-    list      []StdField
-    nameIndex map[string]*StdField
-    byFoldedName map[string]*StdField
-}
-
-//go:noescape
-//go:linkname typeFields encoding/json.typeFields
-func typeFields(_ reflect.Type) StdStructFields
-
-func handleOmitZero(fv StdField, fm *FieldMeta) {
-    if fv.omitZero {
-        fm.Opts |= F_omitzero
-        fm.IsZero = fv.isZero
-    }
-}
-