mikoto2000/devcontainer.vim: コンテナ上で Vim を使った開発をするためのツール。 VSCode Dev Container の Vim 版を目指しています。 の中で、 JSON をマージしたいという要求が出てきたので darccio/mergo: Mergo: merging Go structs and maps since 2013 を試す。
正確に言うと、「構造体・マップをマージするライブラリ」だが、 Marshal 後の JSON でも使えるので試す。
開発環境起動
docker run -it --rm -v "$(pwd):/work" --workdir /work -v "$HOME/.vim:/root/.vim" golang:1.22.1-bookworm
環境構築
go mod init github.com/mikoto2000/golang/json/mergo/firststep
go get dario.cat/mergo
JSON ファイル作成
json/base.json
:
{
"name":"Go",
"image":"mcr.microsoft.com/devcontainers/go:1-1.22-bookworm",
"mounts": [
{
"type": "bind",
"source": "${localEnv:HOME}/.gitconfig",
"target": "/home/vscode/.gitconfig"
}
],
"features":{},
"remoteUser":"vscode"
}
json/additional.json
:
{
"mounts": [
{
"type": "bind",
"source": "${localEnv:HOME}/.vim",
"target": "/home/vscode/.vim"
}
]
}
プログラム実装
JSON のスキーマファイル定義
devcontainer/schema.go
:
package devcontainer
import (
"encoding/json"
)
type Devcontainer struct {
string
Name string
Image
Mounts Mountsinterface{}
Features string
RemoteUser }
type Mounts []Mount
type Mount struct {
string
Type string
Source string
Target }
func UnmarshalDevcontainer(data []byte) (Devcontainer, error) {
var d Devcontainer
:= json.Unmarshal(data, &d)
err return d, err
}
主処理実装
main.go
:
package main
import (
"fmt"
"os"
"dario.cat/mergo"
"github.com/mikoto2000/golang/json/mergo/firststep/devcontainer"
)
const baseJsonPath = "json/base.json"
const additionalJsonPath = "json/additional.json"
func main() {
, err := parseJsonFile("json/base.json")
baseJsonif err != nil {
panic(err)
}
.Printf("=== %s ===\n", baseJsonPath)
fmt.Printf("%+v\n", baseJson)
fmt.Println()
fmt
, err := parseJsonFile("json/additional.json")
additionalJsonif err != nil {
panic(err)
}
.Printf("=== %s ===\n", additionalJsonPath)
fmt.Printf("%+v\n", additionalJson)
fmt.Println()
fmt
// マージオプションは以下を参照
// https://github.com/darccio/mergo/blob/cde9f0ea26cccb1168ee3900cf8ca457bb928c3c/merge.go#L329-L372
.Merge(&baseJson, additionalJson, mergo.WithAppendSlice)
mergo.Printf("=== Merged JSON %s and %s ===\n", baseJsonPath, additionalJsonPath)
fmt.Printf("%+v\n", baseJson)
fmt.Println()
fmt
}
func parseJsonFile(jsonFilePath string) (devcontainer.Devcontainer, error) {
, err := os.ReadFile(jsonFilePath)
jsonContentif err != nil {
return devcontainer.Devcontainer{}, err
}
, err := devcontainer.UnmarshalDevcontainer(jsonContent)
dif err != nil {
return devcontainer.Devcontainer{}, err
}
return d, nil
}
実行
root@a67c959ef4b8:/work# go run main.go
=== json/base.json ===
{Name:Go Image:mcr.microsoft.com/devcontainers/go:1-1.22-bookworm Mounts:[{Type:bind Source:${localEnv:HOME}/.gitconfig Target:/home/vscode/.gitconfig}] Features:map[] RemoteUser:vscode}
=== json/additional.json ===
{Name: Image: Mounts:[{Type:bind Source:${localEnv:HOME}/.vim Target:/home/vscode/.vim}] Features:<nil> RemoteUser:}
=== Merged JSON json/base.json and json/additional.json ===
{Name:Go Image:mcr.microsoft.com/devcontainers/go:1-1.22-bookworm Mounts:[{Type:bind Source:${localEnv:HOME}/.gitconfig Target:/home/vscode/.gitconfig} {Type:bind Source:${localEnv:HOME}/.vim Target:/home/vscode/.vim}] Features:map[] RemoteUser:vscode}
0 件のコメント:
コメントを投稿