JSON编码/解码和RSA证书

Using Go's built-in JSON encoding and RSA certificates, encoding an RSA certificate to JSON and then decoding it again fails. Can anyone tell me why?

Sample code:

package main

import (
    "math/big"
    "bytes"
    "crypto/rsa"
    "crypto/x509"
    "encoding/json"
    "fmt"
)

func main() {
    x := x509.Certificate{}
    N := big.Int{}
    N.SetString("22748727785943691703458259255009028279491017474470365445444638136335844588257736864763884308763893296520197853772438093808627310216929382637891614145169115712146316592081285259872752696564531634381437767246277672628285238806746417464073995314135364153811760424176263991818395775316575483628262670505480241278789196525640591586277923027755459881178666634831466031143685993230414451164180917857690755309066589767418739391025091379117132119476119702352443067398453637494721792111385747721853079909232828234315851102595340792201691113238210441101837352511126798300795766862744529103670862211990583319260851455953450220537", 10)
    x.PublicKey = &rsa.PublicKey{N:&N, E:65537}
    var y x509.Certificate
    b := bytes.Buffer{}
    err := json.NewEncoder(&b).Encode(x)
    if err != nil { fmt.Println(err); return; }
    err = json.NewDecoder(&b).Decode(&y)
    if err != nil { fmt.Println(err) }
}

This fails in the Decode step with:

json: cannot unmarshal number 22748727785943691703458259255009028279491017474470365445444638136335844588257736864763884308763893296520197853772438093808627310216929382637891614145169115712146316592081285259872752696564531634381437767246277672628285238806746417464073995314135364153811760424176263991818395775316575483628262670505480241278789196525640591586277923027755459881178666634831466031143685993230414451164180917857690755309066589767418739391025091379117132119476119702352443067398453637494721792111385747721853079909232828234315851102595340792201691113238210441101837352511126798300795766862744529103670862211990583319260851455953450220537 into Go struct field Certificate.PublicKey of type float64

Playground example

The problem here is that the Certificate type declares PublicKey to be an interface{} and so the JSON unmarshaller has no hints about what type it should unmarshal the public key into. It tries to guess and gets it wrong; even if the large integer was correctly unmarshalled into a math/big.Int object, the PublicKey field would still be a map[string]interface{}, not a crypto/rsa.PublicKey object and so almost certainly not what you want.

To make this work, you would need to write a custom JSON marshaller / unmarshaller; probably encoding the whole certificate as PEM text would be correct way to store it in the JSON output. In my case, I can get away with just not encoding the certificate to JSON at all.