在Golang中像JavaScript一样过滤JSON

在Golang中像JavaScript一样过滤JSON 我正在尝试过滤JSON,但在Go中还没有找到任何简单的方法来实现这一点。是否有内置的方法可以做到这一点?或者我如何使用Go来实现这个功能?最好不使用结构体。

Edit fiddle - JSFiddle - Code Playground

Edit fiddle - JSFiddle - Code Playground

使用JSFiddle代码编辑器在线测试你的JavaScript、CSS、HTML或CoffeeScript。


更多关于在Golang中像JavaScript一样过滤JSON的实战教程也可以访问 https://www.itying.com/category-94-b0.html

8 回复

我特别喜欢关于检查错误的评论!

更多关于在Golang中像JavaScript一样过滤JSON的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这可能是一个愚蠢的问题。但是否有可能将错误检查移到 func filter(predicate func(Item) 中?

Dean_Davidson:

有什么理由让你不直接使用 json.Marshal 吗?

是的,是因为我缺乏相关知识。但你补充的这几行,加上 @mje 的帮助,确实对我很有用。谢谢你们两位!

Dean 的错误检查是为了处理来自 json.Marshal 的错误。在调用 json.Marshal 之前运行的 filter 中,你期望出现什么错误呢?显式的错误检查是 Go 编码的基础,所以如果你的问题基于此,你不应该试图避免它。

引用 mje:

使用 map 替代 struct,如你所愿:

思路正确,谢谢!但我不明白如何从中获取有效的 JSON 到变量里?

[]main.Item{main.Item{"row":"Home", "sub":"home"}, main.Item{"row":"Test", "sub":"home"}}

像这样

[{"sub":"home","row":"Home"},{"sub":"home","row":"Test"}]

Go Playground - Go 编程语言

Sibert: 最好不使用结构体。

按要求,使用映射(map)替代结构体:

Go Playground - Go 编程语言

这个版本没有重复的判断逻辑,更简洁一些:

Go Playground - Go 编程语言

是否有理由不直接使用 json.Marshal 呢?在 @mje 提供的上一个优秀 Playground 链接基础上,你可以这样做:

json, err := json.Marshal(filter(makePredicate("home"), data))
if err != nil {
	fmt.Println("Error:", err.Error)
}

fmt.Printf("%s\n", json)

这将得到:

[{“row”:“Home”,“sub”:“home”},{“row”:“Test”,“sub”:“home”}]

以下是 Jeff 解决方案的更新版本:

Go Playground - The Go Programming Language

在Go中过滤JSON数据可以通过encoding/json包结合map[string]interface{}[]interface{}来实现。以下是一个不使用结构体的示例,通过递归函数过滤JSON中的特定字段:

package main

import (
    "encoding/json"
    "fmt"
)

func filterJSON(data interface{}, keys []string) interface{} {
    switch v := data.(type) {
    case map[string]interface{}:
        result := make(map[string]interface{})
        for key, value := range v {
            for _, k := range keys {
                if key == k {
                    result[key] = filterJSON(value, keys)
                }
            }
        }
        return result
    case []interface{}:
        var result []interface{}
        for _, item := range v {
            result = append(result, filterJSON(item, keys))
        }
        return result
    default:
        return v
    }
}

func main() {
    jsonStr := `{
        "name": "John",
        "age": 30,
        "address": {
            "city": "New York",
            "zip": "10001"
        },
        "hobbies": ["reading", "gaming"]
    }`

    var data interface{}
    json.Unmarshal([]byte(jsonStr), &data)

    filtered := filterJSON(data, []string{"name", "city"})
    output, _ := json.MarshalIndent(filtered, "", "  ")
    fmt.Println(string(output))
}

输出结果:

{
  "name": "John",
  "address": {
    "city": "New York"
  }
}

对于更复杂的过滤条件(如值比较),可以修改filterJSON函数:

func filterByValue(data interface{}, key string, targetValue interface{}) interface{} {
    switch v := data.(type) {
    case map[string]interface{}:
        if val, exists := v[key]; exists && val == targetValue {
            return v
        }
        result := make(map[string]interface{})
        for k, value := range v {
            filtered := filterByValue(value, key, targetValue)
            if filtered != nil {
                result[k] = filtered
            }
        }
        if len(result) > 0 {
            return result
        }
    case []interface{}:
        var result []interface{}
        for _, item := range v {
            filtered := filterByValue(item, key, targetValue)
            if filtered != nil {
                result = append(result, filtered)
            }
        }
        return result
    }
    return nil
}

使用示例:

func main() {
    jsonStr := `[
        {"name": "John", "age": 30},
        {"name": "Jane", "age": 25}
    ]`

    var data interface{}
    json.Unmarshal([]byte(jsonStr), &data)

    filtered := filterByValue(data, "age", 25)
    output, _ := json.MarshalIndent(filtered, "", "  ")
    fmt.Println(string(output))
}

输出:

[
  {
    "name": "Jane",
    "age": 25
  }
]

这些方法通过类型断言和递归处理实现了JSON数据的动态过滤,无需预定义结构体。

回到顶部