我正在尝试为我使用的所有第三方API构建聚合服务, 此聚合服务从我的主系统获取json值,它将此值设置为等效于第三方api密钥的密钥,然后,聚合服务它将向第三方发送请求新的json格式的api。
示例1:
package main
import (
"encoding/json"
"fmt"
"log"
"github.com/tidwall/gjson"
)
func main() {
// mapping JSON
mapB := []byte(`
{
"date": "createdAt",
"clientName": "data.user.name"
}
`)
// from my main system
dataB := []byte(`
{
"createdAt": "2017-05-17T08:52:36.024Z",
"data": {
"user": {
"name": "xxx"
}
}
}
`)
mapJSON := make(map[string]interface{})
dataJSON := make(map[string]interface{})
newJSON := make(map[string]interface{})
err := json.Unmarshal(mapB, &mapJSON)
if err != nil {
log.Panic(err)
}
err = json.Unmarshal(dataB, &dataJSON)
if err != nil {
log.Panic(err)
}
for i := range mapJSON {
r := gjson.GetBytes(dataB, mapJSON[i].(string))
newJSON[i] = r.Value()
}
newB, err := json.MarshalIndent(newJSON, "", " ")
if err != nil {
log.Println(err)
}
fmt.Println(string(newB))
}
输出:
{
"clientName": "xxx",
"date": "2017-05-17T08:52:36.024Z"
}
我使用gjson包从json文档中以简单的方式从我的主系统请求中获取值。
示例-2:
import (
"encoding/json"
"fmt"
"log"
"github.com/tidwall/gjson"
)
func main() {
// mapping JSON
mapB := []byte(`
{
"date": "createdAt",
"clientName": "data.user.name",
"server":{
"google":{
"date" :"createdAt"
}
}
}
`)
// from my main system
dataB := []byte(`
{
"createdAt": "2017-05-17T08:52:36.024Z",
"data": {
"user": {
"name": "xxx"
}
}
}
`)
mapJSON := make(map[string]interface{})
dataJSON := make(map[string]interface{})
newJSON := make(map[string]interface{})
err := json.Unmarshal(mapB, &mapJSON)
if err != nil {
log.Panic(err)
}
err = json.Unmarshal(dataB, &dataJSON)
if err != nil {
log.Panic(err)
}
for i := range mapJSON {
r := gjson.GetBytes(dataB, mapJSON[i].(string))
newJSON[i] = r.Value()
}
newB, err := json.MarshalIndent(newJSON, "", " ")
if err != nil {
log.Println(err)
}
fmt.Println(string(newB))
}
输出:
panic: interface conversion: interface {} is map[string]interface {}, not string
我可以使用https://golang.org/ref/spec#Type_assertions来处理这个错误,但是如果这个json对象有数组并且在这个数组中有json对象....
我的问题是我有不同的api,每个api都有自己的json架构,和我的映射json的方式只能工作 第三方api只有json键值,在这个数组json对象中没有嵌套的json或数组。
有没有办法映射复杂的json架构,或Golang包来帮助我做到这一点?
答案 0 :(得分:2)
修改强>
评论互动和更新后的问题。在我们前进之前,我想提一下。
我只是看着你的
example-2
记住一件事。映射是从一种形式到另一种形式。基本上one known format to targeted format
。必须处理每种数据类型。您无法在逻辑上执行generic
到generic
映射(但技术上可行,但需要更多时间和努力,您可以在此处进行操作)。
我创建了一种方法的样本工作程序;它执行源到目标格式的映射。请参考此计划作为起点,并利用您的创造力来实施您的计划。
游乐场链接:https://play.golang.org/p/MEk_nGcPjZ
说明:示例程序实现了两种不同的源格式到一种目标格式。该计划包括 -
程序中的关键元素:请参阅完整程序的播放链接。
type MappingInfo struct {
TargetKey string
SourceKeyPath string
DataType string
}
地图功能:
func mapIt(mapping []*MappingInfo, parsedResult gjson.Result) map[string]interface{} {
mappedData := make(map[string]interface{})
for _, m := range mapping {
switch m.DataType {
case "time":
mappedData[m.TargetKey] = parsedResult.Get(m.SourceKeyPath).Time()
case "string":
mappedData[m.TargetKey] = parsedResult.Get(m.SourceKeyPath).String()
}
}
return mappedData
}
输出
Provider 1 Result: map[date:2017-05-17 08:52:36.024 +0000 UTC clientName:provider1 username]
Provider 1 JSON: {
"clientName": "provider1 username",
"date": "2017-05-17T08:52:36.024Z"
}
Provider 2 Result: map[date:2017-05-12 06:32:46.014 +0000 UTC clientName:provider2 username]
Provider 2 JSON: {
"clientName": "provider2 username",
"date": "2017-05-12T06:32:46.014Z"
}
祝你好运,编码愉快!
通常将一个结构转换/转换为另一个结构,您必须使用应用程序逻辑来处理它。
正如你在问题中提到的那样:
我的问题是我有不同的api,每个api都有自己的json架构
每个aggregation
系统都是如此。
有效处理此要求的一种方法;是为每个提供者JSON结构和目标JSON结构保持键的映射。
例如:这是一种方法,请根据您的需要选择您的设计。
各种提供商的JSON结构:
// Provider 1 : JSON structrure
{
"createdAt": "2017-05-17T08:52:36.024Z",
"data": {
"user": {
"name": "xxx"
}
}
}
// Provider 2 : JSON structrure
{
"username": "yyy"
"since": "2017-05-17T08:52:36.024Z",
}
目标JSON结构的映射:
jsonMappingByProvider := make(map[string]string)
// Targeted Mapping for Provider 1
jsonMappingByProvider["provider1"] = `
{
"date": "createdAt",
"clientName": "data.user.name"
}
`
// Targeted Mapping for Provider 2
jsonMappingByProvider["provider2"] = `
{
"date": "since",
"clientName": "username"
}
`
现在,根据您正在处理的提供程序,获取映射并将响应JSON映射到目标结构中。
// get the mapping info by provider
mapping := jsonMappingByProvider["provider1"]
// Parse the response JSON
// Do the mapping
通过这种方式,您可以有效地控制每个提供商及其映射。