json 内容未知,要删除的字段也未知
data.json:
{
"a": "hello",
"b": 9527,
"c": {
"d": 123
}
}
假设构建出的程序名叫 app,
希望 app --keys="a,b" --output="result.json"
输出结果为 result.json:
{
"c": {
"d": 123
}
}
刚学 go 没头绪。。。ioutil.ReadFile 读取文件,然后遍历 keys,用 jsoniter.Get 读取值?然后再拼成一个新的 json ?但是值是啥类型也不确定啊。。
解决了,包名为extract
输入data.json
{
"a": 2,
"b": 3,
"c": {
"d": false
}
}
main.go
package main
import (
"fmt"
"io/ioutil"
"os"
"strings"
jsoniter "github.com/json-iterator/go"
)
// Extract 提取JSON
func Extract(extractType string, inputFileName string, keys []string) ([]byte, error) {
content, err := ioutil.ReadFile(inputFileName)
var inputJSON interface{}
var pickJSON map[string]interface{}
if err := jsoniter.Unmarshal(content, &inputJSON); err != nil {
panic(err)
}
if extractType == "pick" {
if err := jsoniter.Unmarshal([]byte("{}"), &pickJSON); err != nil {
panic(err)
}
}
if m, ok := inputJSON.(map[string]interface{}); ok {
for _, key := range keys {
if extractType == "omit" {
if _, exists := m[key]; exists {
delete(m, key)
}
} else {
pickJSON[key] = m[key]
}
}
}
var output []byte
if extractType == "omit" {
output, err = jsoniter.Marshal(inputJSON)
} else {
output, err = jsoniter.Marshal(pickJSON)
}
return output, err
}
func main() {
pluginsKeys := os.Getenv("PLUGIN_KEYS")
extractType := os.Getenv("PLUGIN_TYPE")
inputFileName := os.Getenv("PLUGIN_FILENAME")
outputFileName := os.Getenv("PLUGIN_OUTPUT")
keys := strings.Split(pluginsKeys, ",")
if extractType == "" {
extractType = "omit"
}
if outputFileName == "" {
outputFileName = "result.json"
}
output, err := Extract(extractType, inputFileName, keys)
if err != nil {
panic(err)
}
err = ioutil.WriteFile(outputFileName, output, 0777)
if err != nil {
panic(err)
}
fmt.Println(string(output))
}
测试,编译好后执行
PLUGIN_TYPE=omit PLUGIN_FILENAME=data.json PLUGIN_KEYS=a,b extract
输出
{"c":{"d":false}}
1
KallyDev 2020-04-11 22:46:33 +08:00 via iPhone
|
2
loading 2020-04-11 22:53:06 +08:00 via Android
go 和 json 打交道基本就是结构体。
|
3
Trim21 2020-04-11 22:55:22 +08:00
转成 map[string]interface{},然后删掉字段再转回去
感觉用 go 做这个事情就是费力不讨好。。。 |
4
cmdOptionKana 2020-04-11 22:56:08 +08:00
一般来说,类型应该可以确定的。如果真的不确定,可以用 interface{}
|
5
current 2020-04-11 23:00:28 +08:00
抛个砖
package main import ( "os" "encoding/json" "io/ioutil" "fmt" "strings" ) var ( filename string rm_fields []string ) func parseArg() { if len(os.Args) != 3 { fmt.Println("Usage ./a.out $filename $rmFields") panic(0) } filename = os.Args[1] rm_fields = strings.Split(os.Args[2], ",") } func main() { parseArg() data, e := ioutil.ReadFile(filename) if e != nil { panic(e) } var tmp map[string]interface{} e = json.Unmarshal(data, &tmp) if e != nil { panic(e) } for _, field := range rm_fields { delete(tmp, field) } out, e := json.Marshal(tmp) if e != nil { panic(e) } fmt.Println(string(out)) } |
6
feelinglucky 2020-04-11 23:01:38 +08:00
@Trim21 正解
|
7
current 2020-04-11 23:03:05 +08:00
|
8
leoleoasd 2020-04-11 23:37:34 +08:00
或者用 json.Raw?
|
9
index90 2020-04-11 23:45:19 +08:00
json.Unmarshal 成 map 啊,然后对 map 操作,完了再 json.Marshal 回去
|
10
darrh00 2020-04-11 23:55:27 +08:00
|
11
darrh00 2020-04-11 23:56:18 +08:00
#10
简单一点的 jq 'del(.a,.b)' test.json |
14
yxlimo 2020-04-12 07:18:28 +08:00 via iPhone
|
15
NullErro 2020-04-13 08:33:45 +08:00
python 处理这个不香吗
|
16
guonaihong 2020-04-13 13:34:42 +08:00
试下这个,也挺不错。https://github.com/tidwall/sjson
```go Delete a value: value, _ := sjson.Delete(`{"name":{"first":"Sara","last":"Anderson"}}`, "name.first") println(value) // Output: // {"name":{"last":"Anderson"}} ``` |