This commit is contained in:
程广 2026-02-11 17:26:30 +08:00
commit b9a44c546e
9 changed files with 839 additions and 0 deletions

141
array.go Normal file
View File

@ -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
}
}

15
base.go Normal file
View File

@ -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{}
}

17
doc/require.md Normal file
View File

@ -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)

100
example/main.go Normal file
View File

@ -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)
}

3
go.mod Normal file
View File

@ -0,0 +1,3 @@
module git.kingecg.top/kingecg/gjson
go 1.25.1

4
init.go Normal file
View File

@ -0,0 +1,4 @@
package gjson
// 初始化包时不需要特殊操作
// 所有功能都在各个类型中实现

122
object.go Normal file
View File

@ -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
}
}

252
property.go Normal file
View File

@ -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 ""
}
}

185
values.go Normal file
View File

@ -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
}