How to convert an interface{} to nested tree in Golang

huangapple go评论74阅读模式
英文:

How to convert an interface{} to nested tree in Golang

问题

传入的interface{}将被转换为[]map[string]interface{}。

原始数据类型是[]map[string]interface{}:

[
  {
    "ID": 1,
    "Name": "Root",
    "ParentID": 0,
    "Path": "Root"
  },
  {
    "ID": 2,
    "Name": "Ball",
    "ParentID": 1,
    "Path": "Root/Ball"
  },
  {
    "ID": 3,
    "Name": "Foot",
    "ParentID": 2,
    "Depth": 2,
    "Path": "Root/Ball/Foot"
  }
]

希望得到的json类型为:

[
  {
    "ID": 1,
    "Name": "Root",
    "ParentID": 0,
    "Path": "Root",
    "Child": {
      "ID": 2,
      "Name": "Ball",
      "ParentID": 1,
      "Path": "Root/Ball",
      "Child": {
        "ID": 3,
        "Name": "Foot",
        "ParentID": 2,
        "Depth": 2,
        "Path": "Root/Ball/Foot"
      }
    }
  }
]

如果使用PHP的方法:

$data = Raw data is array()...
$result = array();
$temp = array();

foreach($data as $item) {
    if($item['ParentID'] == 0) {
        $result[$item['ID']] = $item;
        $temp[$item['ID']] =& $result[$item['ID']];
    }else {
        $temp[$item['ParentID']][$item['ID']] = $item;
        $temp[$item['ID']] =& $temp[$item['ParentID']][$item['ID']];
    }
}

return $result;

Golang代码无法运行:

func tree(array interface{}) map[int]*[]map[string]interface{} {

	results := make(map[int]*map[string]interface{})
	temp := make(map[int]map[string]*map[string]interface{})
	for _, item := range maps(array) {

		id := int(item["ID"].(float64))
		pid := int(item["ParentID"].(float64))

		if pid == 0 {
			results[id] = item
			temp[id]["c"] = &results[id]
		} else {
			temp[pid]["c"] = item
			temp[id] = &temp[pid]["c"]
		}
	}
	return results
}

func maps(val interface{}) []map[string]interface{} {
	if b, err := json.Marshal(val); err == nil {
		var maps []map[string]interface{}
		json.Unmarshal(b, &maps)
		return maps
	}
	return nil
}

我的英文不好,只能通过代码和谷歌翻译来表达。希望得到大家的帮助。

英文:

The incoming interface{} will be converted to []map[string]interface{}.

Raw data type is []map[string]interface{} :

[
  {
    "ID": 1,
    "Name": "Root",
    "ParentID": 0,
    "Path": "Root"
  },
  {
    "ID": 2,
    "Name": "Ball",
    "ParentID": 1,
    "Path": "Root/Ball"
  },
  {
    "ID": 3,
    "Name": "Foot",
    "ParentID": 2,
    "Depth": 2,
    "Path": "Root/Ball/Foot"
  }
]

Hope to get type for json:

[
  {
    "ID": 1,
    "Name": "Root",
    "ParentID": 0,
    "Path": "Root",
    "Child": {
      "ID": 2,
      "Name": "Ball",
      "ParentID": 1,
      "Path": "Root/Ball",
      "Child": {
        "ID": 3,
        "Name": "Foot",
        "ParentID": 2,
        "Depth": 2,
        "Path": "Root/Ball/Foot"
      }
    }
  }
]

if methods of php:

$data = Raw data is array()...
    	
$result = array();
    	
$temp = array();
    	
foreach($data as $item) {
    if($item['ParentID'] == 0) {
        $result[$item['ID']] = $item;
        $temp[$item['ID']] =& $result[$item['ID']];
    }else {
        $temp[$item['ParentID']][$item['ID']] = $item;
        $temp[$item['ID']] =& $temp[$item['ParentID']][$item['ID']];
    }
}

return $result

golang is not run:

func tree(array interface{}) map[int]*[]map[string]interface{} {

	results := make(map[int]*map[string]interface{})
	temp := make(map[int]map[string]*map[string]interface{})
	for _, item := range maps(array) {

		id := int(item["ID"].(float64))
		pid := int(item["ParentID"].(float64))

		if pid == 0 {
			results[id] = item
			temp[id]["c"] = &results[id]
		} else {
			temp[pid]["c"] = item
			temp[id] = &temp[pid]["c"]
		}
	}
	return results
}

func maps(val interface{}) []map[string]interface{} {
	if b, err := json.Marshal(val); err == nil {
		var maps []map[string]interface{}
		json.Unmarshal(b, &maps)
		return maps
	}
	return nil
}

my english is not good.
only be expressed by way of code and google translation.
Hope to get everyone's help.

答案1

得分: 0

一个好的开始是介绍以下代码:

type Post struct {
  ID int
  Name string
  ParentID int
  Depth int
  Path string
}

var posts []Post

并使用encoding/json包来将JSON列表Unmarshal到Go语言的变量中。

英文:

A good start would be to introduce

type Post struct {
  ID int
  Name string
  ParentID int
  Depth int
  Path string
}

var posts []Post

and use package encoding/json to Unmarshal the JSON list to a variable in Go.

答案2

得分: 0

解决方案

package main

import (
	"encoding/json"
	"fmt"
)

var indata string = `[
  {
    "ID": 1,
    "Name": "Root",
    "ParentID": 0,
    "Path": "Root"
  },
  {
    "ID": 2,
    "Name": "Ball",
    "ParentID": 1,
    "Path": "Root/Ball"
  },
  {
    "ID": 3,
    "Name": "Foot",
    "ParentID": 2,
    "Depth": 2,
    "Path": "Root/Ball/Foot"
  }
]`

type Node struct {
	ID       int
	Name     string
	ParentID int
	Depth    int
	Path     string
	Child    *Node
}

func main() {
	nodes := []Node{}

	err := json.Unmarshal([]byte(indata), &nodes)
	if err != nil {
		panic(err)
	}

	m := make(map[int]*Node)
	for i, _ := range nodes {
		//fmt.Printf("Setting m[%d] = <node with ID=%d>\n", n.ID, n.ID)
		m[nodes[i].ID] = &nodes[i]
	}

	for i, n := range nodes {
		//fmt.Printf("Setting <node with ID=%d>.Child to <node with ID=%d>\n", n.ID, m[n.ParentID].ID)
		if m[n.ParentID] != nil {
			m[n.ParentID].Child = &nodes[i]
		}
	}

	outdata, err := json.Marshal(m[1])
	if err != nil {
		panic(err)
	}

	fmt.Println(string(outdata))
}


转到 https://play.golang.org/p/CMk1yhEOhd 进行测试。
英文:

Solution

package main
import (
&quot;encoding/json&quot;
&quot;fmt&quot;
)
var indata string = `[
{
&quot;ID&quot;: 1,
&quot;Name&quot;: &quot;Root&quot;,
&quot;ParentID&quot;: 0,
&quot;Path&quot;: &quot;Root&quot;
},
{
&quot;ID&quot;: 2,
&quot;Name&quot;: &quot;Ball&quot;,
&quot;ParentID&quot;: 1,
&quot;Path&quot;: &quot;Root/Ball&quot;
},
{
&quot;ID&quot;: 3,
&quot;Name&quot;: &quot;Foot&quot;,
&quot;ParentID&quot;: 2,
&quot;Depth&quot;: 2,
&quot;Path&quot;: &quot;Root/Ball/Foot&quot;
}
]`
type Node struct {
ID       int
Name     string
ParentID int
Depth    int
Path     string
Child    *Node
}
func main() {
nodes := []Node{}
err := json.Unmarshal([]byte(indata), &amp;nodes)
if err != nil {
panic(err)
}
m := make(map[int]*Node)
for i, _ := range nodes {
//fmt.Printf(&quot;Setting m[%d] = &lt;node with ID=%d&gt;\n&quot;, n.ID, n.ID)
m[nodes[i].ID] = &amp;nodes[i]
}
for i, n := range nodes {
//fmt.Printf(&quot;Setting &lt;node with ID=%d&gt;.Child to &lt;node with ID=%d&gt;\n&quot;, n.ID, m[n.ParentID].ID)
if m[n.ParentID] != nil {
m[n.ParentID].Child = &amp;nodes[i]
}
}
outdata, err := json.Marshal(m[1])
if err != nil {
panic(err)
}
fmt.Println(string(outdata))
}

Go to https://play.golang.org/p/CMk1yhEOhd to test it.

huangapple
  • 本文由 发表于 2017年4月7日 05:04:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/43265724.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定