Upgrade to Pro — share decks privately, control downloads, hide ads and more …

What's New in json/v2? A 10-Minute Overview

What's New in json/v2? A 10-Minute Overview

Avatar for Douglas Shuhei Takeuchi

Douglas Shuhei Takeuchi

August 24, 2025
Tweet

Transcript

  1. About Me Douglas Takeuchi Lead Engineer at OLTA Inc. Favorite

    Accent: British Accent Favorite Place to Visit: Sydney
  2. Agenda 1. Introduction & OLTA's Tech Stack 2. JSON v1

    Recap & Issues 3. JSON v2 Introduction 4. Key Features & Improvements 5. Breaking Changes 6. Performance Comparison 7. Migration Considerations 8. Conclusion
  3. JSON v1 Recap Core Interfaces & Use Cases // Basic

    operations b := `{"name": "John", "age": 20}` var user *User if err := json.Unmarshal(b, &user);err != nil { return err } // Streaming operations reader := strings.NewReader(b) decoder := json.NewDecoder(reader) if err := decoder.Decode(&user); err != nil { return err }
  4. JSON v1 Recap Struct Tags for Control over Marshal/Unmarshal type

    User struct { ID int `json:"id"` // reads and write to 'id' key Name string `json:"name,omitempty"` // omitted when null Address string `json:"address,omitzero"` // omitted when value is 'zero' BirthDay time.Time `json:"-"` // ignored both in Marshal and Unmarshal }
  5. JSON v1 Issues & Limitations Problems with v1 Not True

    Streaming: Encoder/Decoder buffer entire JSON in memory Performance Bottlenecks: O(n²) scenarios in unmarshaling Missing Functionality: Time formatting, custom options
  6. JSON v2 Introduction What's New Option Structs: More control over

    Marshal/Unmarshal Custom Interfaces: Enhanced Marshaler/Unmarshaler New Tag: "format" tag to format Performance Improvements: 2x-10x faster unmarshal Breaking Changes: Default behavior differences
  7. Option Structs for Control Marshal/Unmarshal data, err := json.Marshal( User{ID:

    100, Name:"Brian", Age: 0}, json.OmitZeroStructFields(true), // equivalent to omitzero json.StringifyNumbers(true), // converts numbers to string jsontext.WithIndent(" "), // specify value for indents ) /* output: { "id": "100", "name": "Brian", } */
  8. Custom Marshalers marshaler := json.MarshalFunc( func(v bool) ([]byte, error) {

    if v { return []byte(`"OK"`), nil } return []byte(`"NG"`), nil }, ) data := true b, _ := json.Marshal(data, json.WithMarshalers(marshaler)) fmt.Println(string(b)) // "OK"
  9. New "format" Tag type User struct {BirthDay time.Time `json:"birthDay,format:DateOnly"`} u

    := User{BirthDay: time.Date(2000,12,31,0,0,0,0,time.UTC)} b, _ := json.Marshal(u, jsontext.WithIndent(" ")) fmt.Println(string(b)) /* { "birthDay": "2000-12-31" } */
  10. Performance Improvements Unmarshaling Performance Why v2 is Faster Algorithmic Improvements:

    O(n²) → O(n) scenarios Example: Kubernetes OpenAPI spec became 40x faster Memory Efficiency: Better allocation patterns Optimized Parsing: Improved JSON token handling Marshaling Performance Minimal Improvement: v2 marshaling performance is similar to v1 Focus: v2 prioritizes unmarshaling optimization
  11. Breaking Changes: Default Behavior Important Changes Maps and Slices Handling

    // v1 behavior var m map[string]int json.Marshal(m) // → "null" // v2 behavior var m map[string]int json.Marshal(m) // → "{}" (empty object) Nil vs Empty Values v1: Nil maps/slices become null v2: Nil maps/slices become empty objects/arrays
  12. Migration Considerations Should You Migrate Now? Not Recommended for Production

    Experimental Status: GOEXPERIMENT=jsonv2 required Breaking Changes: Default behavior differences No Backward Compatibility Guarantee Error Messages: May change between versions
  13. How to Enable JSON v2 Environment Setup # Enable JSON

    v2 export GOEXPERIMENT=jsonv2 # Or for specific commands GOEXPERIMENT=jsonv2 go run main.go Code Changes Required // v1 (still works with v2 enabled) import "encoding/json" // v2 (new package) import "encoding/json/v2"
  14. Comparison Summary Aspect JSON v1 JSON v2 Performance Baseline 2x-10x

    faster unmarshaling Memory Usage Buffers all data True streaming Formatting Limited options Full control via Options and tags Default Behavior Nil → null Nil → empty values Production Ready Stable Experimental
  15. Conclusion Key Takeaways 1. JSON v2 brings significant performance improvements

    2. True streaming is now possible 3. Breaking changes require careful migration planning 4. Experimental status means wait for production use 5. Future-focused - prepare for eventual migration
  16. Appendix Additional Resources Go 1.25 Release Notes JSON v2 Design

    Document Performance Benchmarks Migration Guide