Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

[インデックス 11257] ファイルの概要

本コミットは、Go言語の標準ライブラリである encoding/json パッケージにおける、JSON構造体タグのキー名として利用可能な文字の範囲を拡張し、それに関連するコメントとテストを修正するものです。具体的には、タグ名にパーセント記号(%)とスラッシュ(/)の使用を許可するように変更されました。

コミット

commit d4fe9c6a9d8232b9d925dfd1f0e11f4891a5ad27
Author: Mikio Hara <mikioh.mikioh@gmail.com>
Date:   Thu Jan 19 15:33:29 2012 +0900

    encoding/json: fix comments, tweak tests for tag names
    
    R=bradfitz
    CC=golang-dev
    https://golang.org/cl/5558047

GitHub上でのコミットページへのリンク

https://github.com/golang/go/commit/d4fe9c6a9d8232b9d925dfd1f0e11f4891a5ad27

元コミット内容

encoding/json: fix comments, tweak tests for tag names

R=bradfitz
CC=golang-dev
https://golang.org/cl/5558047

変更の背景

Go言語の encoding/json パッケージは、Goの構造体とJSONデータの間のマーシャリング(Go構造体からJSONへの変換)およびアンマーシャリング(JSONからGo構造体への変換)を処理します。構造体のフィールドには「タグ」と呼ばれるメタデータを付与することができ、これによりJSONフィールド名やエンコーディングオプションをカスタマイズできます。

このコミットが行われる以前は、JSONタグのキー名として使用できる文字がUnicodeの文字、数字、ドル記号、ハイフン、アンダースコアに限定されていました。しかし、実際のJSONデータや外部システムとの連携においては、キー名にパーセント記号(%)やスラッシュ(/)が含まれるケースが存在します。例えば、URLエンコードされた文字列やパスのような構造を持つキー名などが考えられます。

この制限は、特定の形式のJSONデータを扱う際に不便であり、開発者がカスタムのマーシャリング/アンマーシャリングロジックを記述する必要があるなど、柔軟性を損なっていました。このコミットは、より広範なJSONキー名のパターンに対応できるように、encoding/json パッケージの柔軟性を向上させることを目的としています。

コミットメッセージに記載されている https://golang.org/cl/5558047 は、この変更がGoのコードレビューシステム(Gerrit)で議論され、承認されたことを示しています。このレビュープロセスを通じて、変更の必要性、実装の詳細、および潜在的な影響が評価されました。

前提知識の解説

Go言語の encoding/json パッケージ

encoding/json パッケージは、GoのプログラムでJSONデータを扱うための主要なパッケージです。

  • json.Marshal: Goの値をJSON形式にエンコードします。
  • json.Unmarshal: JSONデータをGoの値にデコードします。

構造体タグ (Struct Tags)

Goの構造体フィールドには、バッククォート()で囲まれた文字列として「タグ」を付与することができます。これらのタグは、リフレクション(実行時に型情報を検査する機能)を通じてアクセスされ、特定のパッケージ(例: encoding/jsonencoding/xmlgorm`など)によって特別な意味を持ちます。

encoding/json パッケージの場合、json:"keyname,option" の形式でタグを使用します。

  • keyname: JSON出力におけるフィールド名。これが指定されない場合、Goのフィールド名がそのまま使用されます。
  • option: エンコーディングに関する追加オプション(例: omitemptystring-)。
    • omitempty: フィールドがゼロ値(数値の0、文字列の""、スライスのnilなど)の場合、JSON出力から省略されます。
    • string: 数値やブール値をJSON文字列としてエンコードします。
    • -: フィールドをJSONエンコード/デコードの対象から除外します。

例:

type User struct {
    Name  string `json:"user_name"`
    Email string `json:"-"` // このフィールドはJSONに含めない
    Age   int    `json:"age,omitempty"` // ゼロ値の場合は省略
}

Unicode文字、数字、記号

JSONキー名は、一般的に文字列として扱われます。このコミット以前は、encoding/json パッケージが内部的にJSONキー名として有効と判断する文字の集合が限定的でした。これは、JSON仕様自体がキー名に特定の文字を制限しているわけではなく、実装上の判断や慣習によるものです。

  • Unicode letters: 世界中の言語の文字。
  • digits: 0-9の数字。
  • dollar signs ($): ドル記号。
  • hyphens (-): ハイフン。
  • underscores (_): アンダースコア。

このコミットでは、上記のリストに加えて、percent signs (%)slashes (/) が追加されました。

技術的詳細

このコミットの技術的な変更は、主に encoding/json パッケージがJSONタグのキー名を解析する際の内部ロジックと、そのロジックを反映したドキュメントコメント、そしてテストケースの更新に集約されます。

  1. src/pkg/encoding/json/encode.go のコメント修正:

    • このファイルには、json タグのキー名として有効な文字を説明するコメントが含まれています。
    • 変更前は「Unicode letters, digits, dollar signs, hyphens, and underscores」と記述されていました。
    • 変更後は「Unicode letters, digits, dollar signs, percent signs, hyphens, underscores and slashes」と更新され、パーセント記号とスラッシュが追加されたことが明示されました。
    • これは、encoding/json パッケージの内部的なタグ解析ロジックがこれらの文字を有効と認識するように変更されたことを示唆しています。Goの標準ライブラリでは、このようなドキュメントコメントはコードの振る舞いを正確に反映するように維持されます。
  2. src/pkg/encoding/json/tagkey_test.go のテスト修正:

    • このファイルは、JSONタグのキー名のパースが正しく行われることを検証するためのテストケースを含んでいます。
    • basicLatin2xTag 構造体のタグ変更:
      • 変更前: V string json:"$-"`
      • 変更後: V string json:"$%-/"`
      • この変更は、パーセント記号(%)とスラッシュ(/)を含むタグ名が正しくパースされ、有効なキーとして認識されることを確認するためのものです。これにより、これらの文字が実際にJSONタグ名として機能することが保証されます。
    • badCodeTag 構造体のタグ変更:
      • 変更前: Z string json:" !"#%&'()*+,./"`
      • 変更後: Z string json:" !"#&'()*+,."`
      • badCodeTag は、無効な文字を含むタグ名をテストするためのものです。変更前はスラッシュ(/)が無効な文字のリストに含まれていましたが、このコミットによってスラッシュが有効な文字になったため、無効な文字のリストから削除されました。これは、スラッシュがもはや「不正なコード」ではないことを反映しています。
    • structTagObjectKeyTests 配列の期待値変更:
      • basicLatin2xTag に対応するテストエントリの期待されるキー名が、"$-" から "$%-/" に更新されました。これは、basicLatin2xTag 構造体自体のタグ変更と同期しており、テストが新しい有効なタグ名を正しく検証していることを保証します。

これらの変更は、encoding/json パッケージがJSONタグのキー名を解析する際の正規表現や文字セットの定義が内部的に更新された結果として行われています。これにより、開発者はより多様なJSONキー名を持つデータ構造を、Goの構造体タグを使って直接マッピングできるようになり、柔軟性が向上します。

コアとなるコードの変更箇所

src/pkg/encoding/json/encode.go

--- a/src/pkg/encoding/json/encode.go
+++ b/src/pkg/encoding/json/encode.go
@@ -79,7 +79,8 @@ import (
 //    Int64String int64 `json:",string"`
 //
 // The key name will be used if it's a non-empty string consisting of
-// only Unicode letters, digits, dollar signs, hyphens, and underscores.
+// only Unicode letters, digits, dollar signs, percent signs, hyphens,
+// underscores and slashes.
 //
 // Map values encode as JSON objects.
 // The map's key type must be string; the object keys are used directly

src/pkg/encoding/json/tagkey_test.go

--- a/src/pkg/encoding/json/tagkey_test.go
+++ b/src/pkg/encoding/json/tagkey_test.go
@@ -9,7 +9,7 @@ import (
 )
 
 type basicLatin2xTag struct {
-	V string `json:"$-"`
+	V string `json:"$%-/"`
 }
 
 type basicLatin3xTag struct {
@@ -53,7 +53,7 @@ type badFormatTag struct {
 }
 
 type badCodeTag struct {
-	Z string `json:" !\"#%&'()*+,./"`
+	Z string `json:" !\"#&'()*+,."`
 }
 
 var structTagObjectKeyTests = []struct {
@@ -61,7 +61,7 @@ var structTagObjectKeyTests = []struct {
 	value string
 	key   string
 }{
-	{basicLatin2xTag{"2x"}, "2x", "$-"},
+	{basicLatin2xTag{"2x"}, "2x", "$%-/"},
 	{basicLatin3xTag{"3x"}, "3x", "0123456789"},
 	{basicLatin4xTag{"4x"}, "4x", "ABCDEFGHIJKLMO"},
 	{basicLatin5xTag{"5x"}, "4x", "PQRSTUVWXYZ_"},

コアとなるコードの解説

src/pkg/encoding/json/encode.go の変更

この変更は、encoding/json パッケージのドキュメンテーションコメントを更新するものです。具体的には、JSONタグのキー名として有効な文字のリストに「percent signs」(%)と「slashes」(/)が追加されました。

  • 変更前: // only Unicode letters, digits, dollar signs, hyphens, and underscores.
  • 変更後: // only Unicode letters, digits, dollar signs, percent signs, hyphens, // underscores and slashes.

このコメントの更新は、コードの実際の動作変更を反映しています。つまり、encoding/json パッケージの内部的なタグ解析ロジックが、これらの新しい文字を有効なキー名の一部として認識するように修正されたことを示唆しています。Goの標準ライブラリでは、コメントはコードの振る舞いを正確に記述することが非常に重要視されており、このような変更は機能的な変更があったことの明確な証拠となります。

src/pkg/encoding/json/tagkey_test.go の変更

このファイルは、JSONタグのキー名のパースが正しく行われることを検証するための単体テストを含んでいます。

  1. basicLatin2xTag 構造体の定義変更:

    • 変更前: V string json:"$-"`
    • 変更後: V string json:"$%-/"`
    • この変更は、basicLatin2xTag 構造体の V フィールドに付与されているJSONタグを更新しています。新しいタグ "$%-/" は、パーセント記号(%)とスラッシュ(/)を含んでいます。これにより、これらの文字がJSONタグのキー名として正しく扱われることをテストで確認できるようになります。これは、新しい機能(パーセント記号とスラッシュのサポート)が期待通りに動作することを確認するための「ポジティブテストケース」です。
  2. badCodeTag 構造体の定義変更:

    • 変更前: Z string json:" !"#%&'()*+,./"`
    • 変更後: Z string json:" !"#&'()*+,."`
    • badCodeTag は、JSONタグのキー名として無効な文字を含むケースをテストするためのものです。変更前は、スラッシュ(/)が無効な文字のリストに含まれていました。しかし、このコミットによってスラッシュが有効な文字になったため、無効な文字のリストからスラッシュが削除されました。これは、スラッシュがもはや「不正なコード」ではないことを反映した「ネガティブテストケース」の修正です。
  3. structTagObjectKeyTests 配列のテストデータ変更:

    • 変更前: {basicLatin2xTag{"2x"}, "2x", "$-"},
    • 変更後: {basicLatin2xTag{"2x"}, "2x", "$%-/"},
    • この配列は、様々なJSONタグを持つ構造体がどのようにマーシャリングされ、どのようなJSONキーが生成されるかを検証するためのテストデータを含んでいます。basicLatin2xTag に対応するエントリの期待される key の値が、"$-" から "$%-/" に更新されました。これは、basicLatin2xTag 構造体自体のタグ変更と同期しており、テストが新しい有効なタグ名を正しく検証していることを保証します。

これらのコード変更は、encoding/json パッケージがJSONタグのキー名を解析する際の内部的なルールが拡張されたことを明確に示しています。これにより、開発者はより柔軟なJSONキー名を持つデータ構造を、Goの構造体タグを使って直接マッピングできるようになり、外部システムとの連携が容易になります。

関連リンク

  • Go言語 encoding/json パッケージのドキュメント: https://pkg.go.dev/encoding/json
  • Go言語の構造体タグに関する公式ブログ記事 (例: "JSON and Go"): https://go.dev/blog/json (これは一般的な情報源であり、このコミットに直接関連するものではありませんが、背景知識として有用です。)

参考にした情報源リンク

  • Goのコードレビューシステム (Gerrit) の変更リスト: https://golang.org/cl/5558047
    • このリンクは、このコミットがGoの公式リポジトリにマージされる前にレビューされた際の議論やコメントを確認できるため、変更の意図や背景を深く理解する上で非常に重要です。
  • Go言語のGitHubリポジトリ: https://github.com/golang/go
  • JSON (JavaScript Object Notation) の公式ウェブサイト: https://www.json.org/json-en.html
    • JSONの仕様自体はキー名に特定の文字を制限していませんが、このコミットはGoの encoding/json パッケージがより広範なJSONキー名に対応できるようにするためのものです。
  • Unicode Consortium: https://home.unicode.org/
    • Unicode文字セットに関する情報源。