Go 如何将复杂的JSON映射到其他JSON
我正在尝试为我使用的所有第三方API构建聚合服务, 这个聚合服务接受来自我的主系统的json值,它将把这个值放到与第三方api密钥等价的密钥中,然后,聚合服务它将以新的json格式向第三方api发送请求 示例1:Go 如何将复杂的JSON映射到其他JSON,go,Go,我正在尝试为我使用的所有第三方API构建聚合服务, 这个聚合服务接受来自我的主系统的json值,它将把这个值放到与第三方api密钥等价的密钥中,然后,聚合服务它将以新的json格式向第三方api发送请求 示例1: package main import ( "encoding/json" "fmt" "log" "github.com/tidwall/gjson" ) func
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"
}
panic: interface conversion: interface {} is map[string]interface {}, not string
我使用包从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))
}
输出:
{
"clientName": "xxx",
"date": "2017-05-17T08:52:36.024Z"
}
panic: interface conversion: interface {} is map[string]interface {}, not string
我可以通过使用来处理这个错误,但是如果这个json对象有数组,而数组中有json对象呢
我的问题是我有不同的api,每个api都有自己的json模式,我的json映射方法只有在
第三方api仅具有json键值,在此数组json对象中没有嵌套json或数组。
有没有办法映射复杂的json模式或golang包来帮助我实现这一点?编辑:
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 : 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",
}
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"
}
`
评论互动后,与更新后的问题。在我们向前迈进之前,我想提一提
我刚才看了你的示例2
记住一件事。映射是从一种形式映射到另一种形式。基本上,将一种已知格式转换为目标格式
。必须处理每种数据类型。您不能在逻辑上进行generic
到generic
的映射(虽然在技术上可行,但需要花费更多的时间和精力,您可以在这方面进行尝试)
我创建了一种方法的示例工作程序;它将源代码映射到目标格式。把这个计划作为一个起点,运用你的创造力来实施你的计划
游乐场连接:
说明:示例程序将两种不同的源格式转换为一种目标格式。该计划包括-
- 提供程序1的目标映射定义
- 提供程序2的目标映射定义
- 提供者1 JSON
- 提供者2 JSON
- 映射函数
- 目标JSON封送
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 : 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",
}
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"
}
`
输出:
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模式 这适用于每个
聚合系统
一种有效处理这一需求的方法;是保持每个提供者JSON结构和目标JSON结构的键映射
// get the mapping info by provider
mapping := jsonMappingByProvider["provider1"]
// Parse the response JSON
// Do the mapping
例如:这是一种方法,请按照您认为合适的方式进行设计
来自不同提供者的JSON结构:
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 : 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",
}
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结构的映射:
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 : 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",
}
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
通过这种方式,您可以有效地控制每个提供者及其映射。非常感谢您的回答,但我的问题是映射,正如您所知,golang强类型,因为我遇到了很多问题,我正在尝试为这个或golang包找到解决方案,以帮助我映射json。谢谢,你能描述一下你面对的问题吗?所以我可以提供我的输入。我已经更新了答案,看一看。我相信这会给你一个开始的想法,然后你可以接受答案。非常感谢你的帮助和你的时间。