diff --git a/client.go b/client.go
index 9e77cfaf0a89571d54085caf4b6f48d8fb58c42e..9d1151b340504b54b7fdb2061556cc872be0df11 100644
--- a/client.go
+++ b/client.go
@@ -27,6 +27,7 @@ import (
 	"time"
 
 	"git.tuxpa.in/a/zlog/log"
+	jsoniter "github.com/json-iterator/go"
 )
 
 var (
@@ -285,7 +286,7 @@ func (c *Client) call(ctx context.Context, result any, msg *jsonrpcMessage) erro
 	case len(resp.Result) == 0:
 		return ErrNoResult
 	default:
-		return json.Unmarshal(resp.Result, &result)
+		return jsoniter.Unmarshal(resp.Result, &result)
 	}
 }
 
@@ -402,7 +403,7 @@ func (c *Client) BatchCallContext(ctx context.Context, b []BatchElem) error {
 			elem.Error = ErrNoResult
 			continue
 		}
-		elem.Error = json.Unmarshal(resp.Result, elem.Result)
+		elem.Error = jsoniter.Unmarshal(resp.Result, elem.Result)
 	}
 
 	return err
@@ -427,7 +428,7 @@ func (c *Client) newMessage(method string, paramsIn ...any) (*jsonrpcMessage, er
 	msg := &jsonrpcMessage{ID: c.nextID(), Method: method}
 	if paramsIn != nil { // prevent sending "params":null
 		var err error
-		if msg.Params, err = json.Marshal(paramsIn); err != nil {
+		if msg.Params, err = jsoniter.Marshal(paramsIn); err != nil {
 			return nil, err
 		}
 	}
@@ -437,7 +438,7 @@ func (c *Client) newMessageP(method string, paramIn any) (*jsonrpcMessage, error
 	msg := &jsonrpcMessage{ID: c.nextID(), Method: method}
 	if paramIn != nil { // prevent sending "params":null
 		var err error
-		if msg.Params, err = json.Marshal(paramIn); err != nil {
+		if msg.Params, err = jsoniter.Marshal(paramIn); err != nil {
 			return nil, err
 		}
 	}
diff --git a/http.go b/http.go
index cbfa3f5277fc88740b9db6b14d497c1aa9174156..ba29c09c6e61cf0e07b1fe189a1d911e087affaa 100644
--- a/http.go
+++ b/http.go
@@ -29,6 +29,8 @@ import (
 	"net/url"
 	"sync"
 	"time"
+
+	jsoniter "github.com/json-iterator/go"
 )
 
 const (
@@ -177,7 +179,7 @@ func (c *Client) sendBatchHTTP(ctx context.Context, op *requestOp, msgs []*jsonr
 }
 
 func (hc *httpConn) doRequest(ctx context.Context, msg any) (io.ReadCloser, error) {
-	body, err := json.Marshal(msg)
+	body, err := jsoniter.Marshal(msg)
 	if err != nil {
 		return nil, err
 	}
diff --git a/json.go b/json.go
index a22414bd697e4ddf927bf2f36a27bf7511257271..f73fc32952d2ad7435cd8ad99f7ae3014c99aad1 100644
--- a/json.go
+++ b/json.go
@@ -92,7 +92,7 @@ func (msg *jsonrpcMessage) namespace() string {
 }
 
 func (msg *jsonrpcMessage) String() string {
-	b, _ := json.Marshal(msg)
+	b, _ := jsoniter.Marshal(msg)
 	return string(b)
 }
 
@@ -267,7 +267,7 @@ func (c *jsonCodec) closed() <-chan any {
 func parseMessage(raw json.RawMessage) ([]*jsonrpcMessage, bool) {
 	if !isBatch(raw) {
 		msgs := []*jsonrpcMessage{{}}
-		json.Unmarshal(raw, &msgs[0])
+		jsoniter.Unmarshal(raw, &msgs[0])
 		return msgs, false
 	}
 	dec := json.NewDecoder(bytes.NewReader(raw))
diff --git a/protocol.go b/protocol.go
index 9fa8c7e1410039515a67e1737e55b21138e86b22..a8fd134eed5cfa06638ef01bfa9a1240cb94df3c 100644
--- a/protocol.go
+++ b/protocol.go
@@ -31,7 +31,7 @@ type Request struct {
 
 func NewRequest(ctx context.Context, id string, method string, params any) *Request {
 	r := &Request{ctx: ctx}
-	pms, _ := json.Marshal(params)
+	pms, _ := jsoniter.Marshal(params)
 	r.msg = jsonrpcMessage{
 		ID:     NewStringIDPtr(id),
 		Method: method,
diff --git a/wire.go b/wire.go
index 9d2c28231b1ce7740664cc8742e44dea739a28c2..08957b56257aa621d8269254a70ae141b2b6bb03 100644
--- a/wire.go
+++ b/wire.go
@@ -3,6 +3,8 @@ package jrpc
 import (
 	"encoding/json"
 	"fmt"
+
+	jsoniter "github.com/json-iterator/go"
 )
 
 // Version represents a JSON-RPC version.
@@ -21,13 +23,13 @@ var (
 
 // MarshalJSON implements json.Marshaler.
 func (version) MarshalJSON() ([]byte, error) {
-	return json.Marshal(Version)
+	return jsoniter.Marshal(Version)
 }
 
 // UnmarshalJSON implements json.Unmarshaler.
 func (version) UnmarshalJSON(data []byte) error {
 	version := ""
-	if err := json.Unmarshal(data, &version); err != nil {
+	if err := jsoniter.Unmarshal(data, &version); err != nil {
 		return fmt.Errorf("failed to Unmarshal: %w", err)
 	}
 	if version != Version {
@@ -93,12 +95,12 @@ func (id *ID) RawMessage() json.RawMessage {
 		return null
 	}
 	if id.name != "" {
-		ans, err := json.Marshal(id.name)
+		ans, err := jsoniter.Marshal(id.name)
 		if err == nil {
 			return ans
 		}
 	}
-	ans, err := json.Marshal(id.number)
+	ans, err := jsoniter.Marshal(id.number)
 	if err == nil {
 		return ans
 	}
@@ -114,18 +116,18 @@ func (id *ID) MarshalJSON() ([]byte, error) {
 		return null, nil
 	}
 	if id.name != "" {
-		return json.Marshal(id.name)
+		return jsoniter.Marshal(id.name)
 	}
-	return json.Marshal(id.number)
+	return jsoniter.Marshal(id.number)
 }
 
 // UnmarshalJSON implements json.Unmarshaler.
 func (id *ID) UnmarshalJSON(data []byte) error {
 	*id = ID{}
-	if err := json.Unmarshal(data, &id.number); err == nil {
+	if err := jsoniter.Unmarshal(data, &id.number); err == nil {
 		return nil
 	}
-	if err := json.Unmarshal(data, &id.name); err == nil {
+	if err := jsoniter.Unmarshal(data, &id.name); err == nil {
 		return nil
 	}
 	id.null = true