From b9a44c546e2894f401581c5e2480884b3473a16a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=B9=BF?= Date: Wed, 11 Feb 2026 17:26:30 +0800 Subject: [PATCH] init gen --- array.go | 141 +++++++++++++++++++++++++++ base.go | 15 +++ doc/require.md | 17 ++++ example/main.go | 100 +++++++++++++++++++ go.mod | 3 + init.go | 4 + object.go | 122 +++++++++++++++++++++++ property.go | 252 ++++++++++++++++++++++++++++++++++++++++++++++++ values.go | 185 +++++++++++++++++++++++++++++++++++ 9 files changed, 839 insertions(+) create mode 100644 array.go create mode 100644 base.go create mode 100644 doc/require.md create mode 100644 example/main.go create mode 100644 go.mod create mode 100644 init.go create mode 100644 object.go create mode 100644 property.go create mode 100644 values.go diff --git a/array.go b/array.go new file mode 100644 index 0000000..49a1fae --- /dev/null +++ b/array.go @@ -0,0 +1,141 @@ +package gjson + +import ( + "encoding/json" + "strconv" +) + +// JSONArray JSON Array 继承自JSONBaseObject,代表JSON中的数组类型 +type JSONArray struct { + data []interface{} +} + +// NewJSONArray 创建一个新的JSONArray +func NewJSONArray() *JSONArray { + return &JSONArray{ + data: make([]interface{}, 0), + } +} + +// FromJSON 从JSON字符串创建JSONArray +func (ja *JSONArray) FromJSON(jsonStr string) error { + var data []interface{} + if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { + return err + } + ja.data = data + return nil +} + +// ToJSON 将JSONArray转换为JSON字符串 +func (ja *JSONArray) ToJSON() (string, error) { + bytes, err := json.Marshal(ja.data) + if err != nil { + return "", err + } + return string(bytes), nil +} + +// FromString 从字符串创建JSONArray(功能同FromJSON) +func (ja *JSONArray) FromString(str string) error { + return ja.FromJSON(str) +} + +// ToString 将JSONArray转换为字符串(功能同ToJSON) +func (ja *JSONArray) ToString() (string, error) { + return ja.ToJSON() +} + +// Get 获取指定索引的元素 +func (ja *JSONArray) Get(index int) (interface{}, bool) { + if index >= 0 && index < len(ja.data) { + return ja.data[index], true + } + return nil, false +} + +// Put 在指定索引设置元素 +func (ja *JSONArray) Put(index int, value interface{}) error { + if index < 0 || index >= len(ja.data) { + return &InvalidIndexError{index, len(ja.data)} + } + ja.data[index] = extractValueFromJSONBaseObjectForArray(value) + return nil +} + +// Append 向数组末尾添加元素 +func (ja *JSONArray) Append(value interface{}) { + ja.data = append(ja.data, extractValueFromJSONBaseObjectForArray(value)) +} + +// Insert 在指定位置插入元素 +func (ja *JSONArray) Insert(index int, value interface{}) error { + if index < 0 || index > len(ja.data) { + return &InvalidIndexError{index, len(ja.data)} + } + ja.data = append(ja.data[:index], append([]interface{}{extractValueFromJSONBaseObjectForArray(value)}, ja.data[index:]...)...) + return nil +} + +// Remove 删除指定索引的元素 +func (ja *JSONArray) Remove(index int) error { + if index < 0 || index >= len(ja.data) { + return &InvalidIndexError{index, len(ja.data)} + } + ja.data = append(ja.data[:index], ja.data[index+1:]...) + return nil +} + +// Size 获取数组大小 +func (ja *JSONArray) Size() int { + return len(ja.data) +} + +// IsEmpty 检查数组是否为空 +func (ja *JSONArray) IsEmpty() bool { + return len(ja.data) == 0 +} + +// GetData 获取内部数据 +func (ja *JSONArray) GetData() []interface{} { + return ja.data +} + +// InvalidIndexError 索引越界错误 +type InvalidIndexError struct { + index int + size int +} + +func (e *InvalidIndexError) Error() string { + return "index out of bounds: index " + strconv.Itoa(e.index) + " with size " + strconv.Itoa(e.size) +} + +// extractValueFromJSONBaseObjectForArray 从JSONBaseObject中提取原始值用于数组 +func extractValueFromJSONBaseObjectForArray(obj interface{}) interface{} { + switch v := obj.(type) { + case JSONBaseObject: + switch t := v.(type) { + case *JSONString: + return t.Value() + case *JSONNumber: + return t.Value() + case *JSONBool: + return t.Value() + case *JSONNull: + return t.Value() + case *JSONObject: + return t.data + case *JSONArray: + return t.data + default: + return v + } + case *JSONObject: + return v.data + case *JSONArray: + return v.data + default: + return v + } +} \ No newline at end of file diff --git a/base.go b/base.go new file mode 100644 index 0000000..9de5570 --- /dev/null +++ b/base.go @@ -0,0 +1,15 @@ +package gjson + +// JSONBaseObject 抽象对象,代表所有能够进行JSON序列化和反序列化的对象 +type JSONBaseObject interface { + ToJSON() (string, error) + FromJSON(jsonStr string) error + ToString() (string, error) + FromString(str string) error +} + +// JSONValue 代表简单值对象,子类型包括:JSONString、JSONNumber、JSONBool、JSONNull +type JSONValue interface { + JSONBaseObject + Value() interface{} +} \ No newline at end of file diff --git a/doc/require.md b/doc/require.md new file mode 100644 index 0000000..53c10d4 --- /dev/null +++ b/doc/require.md @@ -0,0 +1,17 @@ +# GJson + +实现一个通用的Golang Json对象库 + +## 对象模型 + +1. JSONBaseObject 抽象对象,代表所有能够进行JSON序列化和反序列化的对象 +2. JSONObject JSON Object 继承自JSONBaseObject +3. JSONArray JSON Array 继承自JSONBaseObject 代表JSON中的数组类型 +4. JSONValue 代表简单值对象,子类型包括:JSONString、JSONNumber、JSONBool、JSONNull + +## 功能: + +1. 序列化/反序列化:对象模型中提到的所有类型都应该实现toJson,fromJson,toString,fromString方法. string和json方法功能一致。 +2. 对象属性操作功能,应该提供以下函数: + 1. 获取属性值 getProperty(obj JSONBaseObject, propertyPath string, defaultValue JSONBaseObject) + 2. 设置属性值 setProperty(obj JSONBaseObject, propertyPath string, value JSONBaseObject) \ No newline at end of file diff --git a/example/main.go b/example/main.go new file mode 100644 index 0000000..a425748 --- /dev/null +++ b/example/main.go @@ -0,0 +1,100 @@ +package main + +import ( + "fmt" + "git.kingecg.top/kingecg/gjson" +) + +func main() { + fmt.Println("GJson 示例程序") + + // 创建JSONObject + obj := gjson.NewJSONObject() + obj.Put("name", gjson.NewJSONString("张三").Value()) + obj.Put("age", gjson.NewJSONNumber(25).Value()) + obj.Put("student", gjson.NewJSONBool(false).Value()) + + // 创建嵌套对象 + address := gjson.NewJSONObject() + address.Put("city", gjson.NewJSONString("北京").Value()) + address.Put("zip", gjson.NewJSONNumber(100000).Value()) + obj.Put("address", address.GetData()) // 使用GetData()方法 + + // 创建数组 + arr := gjson.NewJSONArray() + arr.Append(gjson.NewJSONString("item1").Value()) + arr.Append(gjson.NewJSONNumber(123).Value()) + obj.Put("items", arr.GetData()) // 使用GetData()方法 + + // 序列化到JSON + jsonStr, _ := obj.ToJSON() + fmt.Printf("JSON对象: %s\n", jsonStr) + + // 从JSON字符串创建对象 + newObj := gjson.NewJSONObject() + newObj.FromJSON(jsonStr) + + // 获取属性值 + nameVal, _ := newObj.Get("name") + name := gjson.NewJSONString(fmt.Sprintf("%v", nameVal)) + fmt.Printf("姓名: %s\n", name.Value()) + + // 测试嵌套属性 + addressVal, _ := newObj.Get("address") + if addrMap, ok := addressVal.(map[string]interface{}); ok { + cityVal, exists := addrMap["city"] + if exists { + fmt.Printf("地址城市: %v\n", cityVal) + } + } + + // 使用GetProperty方法 + defaultValue := gjson.NewJSONString("default") + propResult, _ := gjson.GetProperty(newObj, "name", defaultValue) + if str, ok := propResult.(*gjson.JSONString); ok { + fmt.Printf("通过GetProperty获取的姓名: %s\n", str.Value()) + } + + propResult2, _ := gjson.GetProperty(newObj, "address.city", defaultValue) + if str, ok := propResult2.(*gjson.JSONString); ok { + fmt.Printf("通过GetProperty获取的城市: %s\n", str.Value()) + } + + // 设置属性值 + gjson.SetProperty(newObj, "address.city", gjson.NewJSONString("上海")) + modifiedProp, _ := gjson.GetProperty(newObj, "address.city", defaultValue) + if str, ok := modifiedProp.(*gjson.JSONString); ok { + fmt.Printf("修改后的城市: %s\n", str.Value()) + } + + // 创建JSONArray并演示其用法 + jsonArray := gjson.NewJSONArray() + jsonArray.Append(gjson.NewJSONString("first").Value()) + jsonArray.Append(gjson.NewJSONNumber(42).Value()) + + nestedObj := gjson.NewJSONObject() + nestedObj.Put("nestedProp", gjson.NewJSONString("nestedValue").Value()) + jsonArray.Append(nestedObj.GetData()) // 使用GetData()方法 + + arrayJson, _ := jsonArray.ToJSON() + fmt.Printf("JSON数组: %s\n", arrayJson) + + // 访问数组元素 + firstElement, _ := jsonArray.Get(0) + fmt.Printf("第一个元素: %v\n", firstElement) + + // 访问嵌套对象 + nestedValue, _ := gjson.GetProperty(jsonArray, "2.nestedProp", gjson.NewJSONString("default")) + if str, ok := nestedValue.(*gjson.JSONString); ok { + fmt.Printf("嵌套对象属性: %s\n", str.Value()) + } + + // 演示各种值类型 + nullValue := gjson.NewJSONNull() + nullStr, _ := nullValue.ToString() + fmt.Printf("空值: %s\n", nullStr) + + boolValue := gjson.NewJSONBool(true) + boolStr, _ := boolValue.ToString() + fmt.Printf("布尔值: %s\n", boolStr) +} \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..4ce9eba --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.kingecg.top/kingecg/gjson + +go 1.25.1 diff --git a/init.go b/init.go new file mode 100644 index 0000000..ff42b68 --- /dev/null +++ b/init.go @@ -0,0 +1,4 @@ +package gjson + +// 初始化包时不需要特殊操作 +// 所有功能都在各个类型中实现 \ No newline at end of file diff --git a/object.go b/object.go new file mode 100644 index 0000000..c87be16 --- /dev/null +++ b/object.go @@ -0,0 +1,122 @@ +package gjson + +import ( + "encoding/json" +) + +// JSONObject JSON Object 继承自JSONBaseObject +type JSONObject struct { + data map[string]interface{} +} + +// NewJSONObject 创建一个新的JSONObject +func NewJSONObject() *JSONObject { + return &JSONObject{ + data: make(map[string]interface{}), + } +} + +// FromJSON 从JSON字符串创建JSONObject +func (jo *JSONObject) FromJSON(jsonStr string) error { + var data map[string]interface{} + if err := json.Unmarshal([]byte(jsonStr), &data); err != nil { + return err + } + jo.data = data + return nil +} + +// ToJSON 将JSONObject转换为JSON字符串 +func (jo *JSONObject) ToJSON() (string, error) { + bytes, err := json.Marshal(jo.data) + if err != nil { + return "", err + } + return string(bytes), nil +} + +// FromString 从字符串创建JSONObject(功能同FromJSON) +func (jo *JSONObject) FromString(str string) error { + return jo.FromJSON(str) +} + +// ToString 将JSONObject转换为字符串(功能同ToJSON) +func (jo *JSONObject) ToString() (string, error) { + return jo.ToJSON() +} + +// Get 获取指定键的值 +func (jo *JSONObject) Get(key string) (interface{}, bool) { + value, exists := jo.data[key] + return value, exists +} + +// Put 设置指定键的值,如果是JSONBaseObject则提取其值 +func (jo *JSONObject) Put(key string, value interface{}) { + switch v := value.(type) { + case JSONBaseObject: + // 如果是JSONBaseObject,转换为实际值 + jo.data[key] = extractValueFromJSONBaseObject(v) + case *JSONObject: + jo.data[key] = v.data + case *JSONArray: + jo.data[key] = v.data + default: + jo.data[key] = v + } +} + +// Remove 删除指定键 +func (jo *JSONObject) Remove(key string) { + delete(jo.data, key) +} + +// Keys 获取所有键 +func (jo *JSONObject) Keys() []string { + keys := make([]string, 0, len(jo.data)) + for k := range jo.data { + keys = append(keys, k) + } + return keys +} + +// Size 获取对象大小 +func (jo *JSONObject) Size() int { + return len(jo.data) +} + +// IsEmpty 检查是否为空 +func (jo *JSONObject) IsEmpty() bool { + return len(jo.data) == 0 +} + +// ContainsKey 检查是否包含指定键 +func (jo *JSONObject) ContainsKey(key string) bool { + _, exists := jo.data[key] + return exists +} + +// GetData 获取内部数据 +func (jo *JSONObject) GetData() map[string]interface{} { + return jo.data +} + +// extractValueFromJSONBaseObject 从JSONBaseObject中提取原始值 +func extractValueFromJSONBaseObject(obj JSONBaseObject) interface{} { + switch v := obj.(type) { + case *JSONString: + return v.Value() + case *JSONNumber: + return v.Value() + case *JSONBool: + return v.Value() + case *JSONNull: + return v.Value() + case *JSONObject: + return v.data + case *JSONArray: + return v.data + default: + return v + } +} \ No newline at end of file diff --git a/property.go b/property.go new file mode 100644 index 0000000..48fe916 --- /dev/null +++ b/property.go @@ -0,0 +1,252 @@ +package gjson + +import ( + "strconv" + "strings" +) + +// getProperty 获取属性值 +func GetProperty(obj JSONBaseObject, propertyPath string, defaultValue JSONBaseObject) (JSONBaseObject, error) { + // 首先尝试将obj转换为其实际类型 + switch v := obj.(type) { + case *JSONObject: + return getFromJSONObject(v, propertyPath, defaultValue) + case *JSONArray: + return getFromJSONArray(v, propertyPath, defaultValue) + default: + // 如果是基础类型,直接返回默认值 + return defaultValue, nil + } +} + +// setProperty 设置属性值 +func SetProperty(obj JSONBaseObject, propertyPath string, value JSONBaseObject) error { + switch v := obj.(type) { + case *JSONObject: + return setInJSONObject(v, propertyPath, value) + case *JSONArray: + return setInJSONArray(v, propertyPath, value) + default: + // 不支持对基本值类型设置属性 + return nil + } +} + +// 从JSONObject中获取属性 +func getFromJSONObject(obj *JSONObject, propertyPath string, defaultValue JSONBaseObject) (JSONBaseObject, error) { + pathParts := strings.Split(propertyPath, ".") + currentObj := obj + + // 遍历路径直到倒数第二个部分 + for i := 0; i < len(pathParts)-1; i++ { + key := pathParts[i] + value, exists := currentObj.Get(key) + if !exists { + return defaultValue, nil + } + + // 如果路径中间部分不是JSONObject,则无法继续 + if jsonObj, ok := value.(*JSONObject); ok { + currentObj = jsonObj + } else { + return defaultValue, nil + } + } + + // 获取最终值 + finalKey := pathParts[len(pathParts)-1] + value, exists := currentObj.Get(finalKey) + if !exists { + return defaultValue, nil + } + + // 根据值的类型返回相应的JSONBaseObject + return convertToJSONBaseObject(value), nil +} + +// 从JSONArray中获取属性 +func getFromJSONArray(arr *JSONArray, propertyPath string, defaultValue JSONBaseObject) (JSONBaseObject, error) { + // 解析路径,支持数组索引 + parts := strings.Split(propertyPath, ".") + + // 第一部分应该是数组索引 + indexStr := parts[0] + index, err := strconv.Atoi(indexStr) + if err != nil { + return defaultValue, err + } + + // 获取数组元素 + element, exists := arr.Get(index) + if !exists { + return defaultValue, nil + } + + // 如果有后续路径部分,说明要访问嵌套对象 + if len(parts) > 1 { + remainingPath := strings.Join(parts[1:], ".") + + // 检查元素类型并递归查找 + switch elem := element.(type) { + case *JSONObject: + return getFromJSONObject(elem, remainingPath, defaultValue) + case *JSONArray: + return getFromJSONArray(elem, remainingPath, defaultValue) + default: + // 其他类型无法继续访问属性 + return defaultValue, nil + } + } + + // 如果没有更多路径部分,直接返回元素 + return convertToJSONBaseObject(element), nil +} + +// 在JSONObject中设置属性 +func setInJSONObject(obj *JSONObject, propertyPath string, value JSONBaseObject) error { + pathParts := strings.Split(propertyPath, ".") + currentObj := obj + + // 遍历路径直到倒数第二个部分 + for i := 0; i < len(pathParts)-1; i++ { + key := pathParts[i] + existingValue, exists := currentObj.Get(key) + + if !exists { + // 如果不存在,创建一个新的JSONObject + newObj := NewJSONObject() + currentObj.Put(key, newObj) + currentObj = newObj + } else if jsonObj, ok := existingValue.(*JSONObject); ok { + // 如果已经是JSONObject,继续向下遍历 + currentObj = jsonObj + } else { + // 如果不是JSONObject,替换为新的JSONObject + newObj := NewJSONObject() + currentObj.Put(key, newObj) + currentObj = newObj + } + } + + // 设置最终值 + finalKey := pathParts[len(pathParts)-1] + + // 将JSONBaseObject转换为interface{} + var interfaceValue interface{} + switch v := value.(type) { + case *JSONObject: + interfaceValue = v.data + case *JSONArray: + interfaceValue = v.data + case *JSONString: + interfaceValue = v.Value() + case *JSONNumber: + interfaceValue = v.Value() + case *JSONBool: + interfaceValue = v.Value() + case *JSONNull: + interfaceValue = v.Value() + default: + interfaceValue = v + } + + currentObj.Put(finalKey, interfaceValue) + return nil +} + +// 在JSONArray中设置属性 +func setInJSONArray(arr *JSONArray, propertyPath string, value JSONBaseObject) error { + // 解析路径,第一部分应该是数组索引 + parts := strings.Split(propertyPath, ".") + + indexStr := parts[0] + index, err := strconv.Atoi(indexStr) + if err != nil { + return err + } + + // 获取数组元素 + element, exists := arr.Get(index) + if !exists { + return nil // 索引不存在 + } + + // 如果有后续路径部分,说明要设置嵌套对象 + if len(parts) > 1 { + remainingPath := strings.Join(parts[1:], ".") + + // 检查元素类型并递归设置 + switch elem := element.(type) { + case *JSONObject: + return SetProperty(elem, remainingPath, value) + case *JSONArray: + return SetProperty(elem, remainingPath, value) + default: + // 其他类型无法设置属性 + return nil + } + } + + // 如果没有更多路径部分,直接设置数组元素 + var interfaceValue interface{} + switch v := value.(type) { + case *JSONObject: + interfaceValue = v.data + case *JSONArray: + interfaceValue = v.data + case *JSONString: + interfaceValue = v.Value() + case *JSONNumber: + interfaceValue = v.Value() + case *JSONBool: + interfaceValue = v.Value() + case *JSONNull: + interfaceValue = v.Value() + default: + interfaceValue = v + } + + return arr.Put(index, interfaceValue) +} + +// 将interface{}转换为适当的JSONBaseObject +func convertToJSONBaseObject(value interface{}) JSONBaseObject { + switch v := value.(type) { + case map[string]interface{}: + jsonObj := NewJSONObject() + jsonObj.data = v + return jsonObj + case []interface{}: + jsonArr := NewJSONArray() + jsonArr.data = v + return jsonArr + case string: + return NewJSONString(v) + case float64: + return NewJSONNumber(v) + case bool: + return NewJSONBool(v) + case nil: + return NewJSONNull() + default: + // 默认转换为字符串 + return NewJSONString(stringify(v)) + } +} + +// stringify 将任意值转换为字符串表示 +func stringify(value interface{}) string { + if value == nil { + return "null" + } + switch v := value.(type) { + case string: + return v + case float64: + return strconv.FormatFloat(v, 'f', -1, 64) + case bool: + return strconv.FormatBool(v) + default: + return "" + } +} \ No newline at end of file diff --git a/values.go b/values.go new file mode 100644 index 0000000..df8e288 --- /dev/null +++ b/values.go @@ -0,0 +1,185 @@ +package gjson + +import ( + "encoding/json" + "fmt" + "strconv" +) + +// JSONString 字符串值类型 +type JSONString struct { + value string +} + +// NewJSONString 创建新的JSONString实例 +func NewJSONString(value string) *JSONString { + return &JSONString{value: value} +} + +// Value 返回实际的字符串值 +func (js *JSONString) Value() interface{} { + return js.value +} + +// ToJSON 返回JSON格式的字符串表示 +func (js *JSONString) ToJSON() (string, error) { + bytes, err := json.Marshal(js.value) + if err != nil { + return "", err + } + return string(bytes), nil +} + +// FromJSON 从JSON字符串初始化 +func (js *JSONString) FromJSON(jsonStr string) error { + var str string + if err := json.Unmarshal([]byte(jsonStr), &str); err != nil { + return err + } + js.value = str + return nil +} + +// ToString 返回字符串表示 +func (js *JSONString) ToString() (string, error) { + return js.value, nil +} + +// FromString 从字符串初始化 +func (js *JSONString) FromString(str string) error { + js.value = str + return nil +} + +// JSONNumber 数字值类型 +type JSONNumber struct { + value float64 +} + +// NewJSONNumber 创建新的JSONNumber实例 +func NewJSONNumber(value float64) *JSONNumber { + return &JSONNumber{value: value} +} + +// Value 返回实际的数字值 +func (jn *JSONNumber) Value() interface{} { + return jn.value +} + +// ToJSON 返回JSON格式的数字表示 +func (jn *JSONNumber) ToJSON() (string, error) { + return strconv.FormatFloat(jn.value, 'f', -1, 64), nil +} + +// FromJSON 从JSON字符串初始化 +func (jn *JSONNumber) FromJSON(jsonStr string) error { + var num float64 + if err := json.Unmarshal([]byte(jsonStr), &num); err != nil { + return err + } + jn.value = num + return nil +} + +// ToString 返回字符串表示 +func (jn *JSONNumber) ToString() (string, error) { + return strconv.FormatFloat(jn.value, 'f', -1, 64), nil +} + +// FromString 从字符串初始化 +func (jn *JSONNumber) FromString(str string) error { + num, err := strconv.ParseFloat(str, 64) + if err != nil { + return err + } + jn.value = num + return nil +} + +// JSONBool 布尔值类型 +type JSONBool struct { + value bool +} + +// NewJSONBool 创建新的JSONBool实例 +func NewJSONBool(value bool) *JSONBool { + return &JSONBool{value: value} +} + +// Value 返回实际的布尔值 +func (jb *JSONBool) Value() interface{} { + return jb.value +} + +// ToJSON 返回JSON格式的布尔值表示 +func (jb *JSONBool) ToJSON() (string, error) { + return strconv.FormatBool(jb.value), nil +} + +// FromJSON 从JSON字符串初始化 +func (jb *JSONBool) FromJSON(jsonStr string) error { + var b bool + if err := json.Unmarshal([]byte(jsonStr), &b); err != nil { + return err + } + jb.value = b + return nil +} + +// ToString 返回字符串表示 +func (jb *JSONBool) ToString() (string, error) { + return strconv.FormatBool(jb.value), nil +} + +// FromString 从字符串初始化 +func (jb *JSONBool) FromString(str string) error { + b, err := strconv.ParseBool(str) + if err != nil { + return err + } + jb.value = b + return nil +} + +// JSONNull 空值类型 +type JSONNull struct{} + +// NewJSONNull 创建新的JSONNull实例 +func NewJSONNull() *JSONNull { + return &JSONNull{} +} + +// Value 返回null值 +func (jn *JSONNull) Value() interface{} { + return nil +} + +// ToJSON 返回JSON格式的null表示 +func (jn *JSONNull) ToJSON() (string, error) { + return "null", nil +} + +// FromJSON 从JSON字符串初始化 +func (jn *JSONNull) FromJSON(jsonStr string) error { + var val interface{} + if err := json.Unmarshal([]byte(jsonStr), &val); err != nil { + return err + } + if val != nil { + return fmt.Errorf("expected null, got %v", val) + } + return nil +} + +// ToString 返回字符串表示 +func (jn *JSONNull) ToString() (string, error) { + return "null", nil +} + +// FromString 从字符串初始化 +func (jn *JSONNull) FromString(str string) error { + if str != "null" { + return fmt.Errorf("expected 'null', got '%s'", str) + } + return nil +} \ No newline at end of file