英文:
Parsing nested list does not go down to level 3
问题
我有一个表示菜单项的JSON。
菜单项可以有子菜单项,而子菜单项又可以有另一个子菜单项,依此类推。
输入的JSON通过父ID关联菜单项。我试图将其转换为每个菜单项都有其子菜单项的模型。
子菜单项最多有三层。我已经成功解析了前两层,但是不知道为什么第三层没有被解析。我已经为这个问题调试了几个小时了。希望能得到一些帮助。
menu2.sjon
[
{
"category_id": 4,
"category_id_400": "'SCHOO",
"name": "School Supplies",
"parent_id": 2,
"position": 2,
"level": 2,
"status": 1,
"url": "http://www.booksrus.kw/sa-en/school-supplies.html"
},
{
"category_id": 141,
"category_id_400": "'SCHBA",
"name": "School Bags",
"parent_id": 4,
"position": 12,
"level": 3,
"status": 1,
"url": "http://www.booksrus.kw/sa-en/school-supplies/school-bags.html"
},
{
"category_id": 269,
"category_id_400": "'AEP",
"name": "Bags Knapsack with Trolley",
"parent_id": 141,
"position": 1,
"level": 4,
"status": 1,
"url": "http://www.booksrus.kw/sa-en/school-supplies/school-bags/bags-knapsack-with-trolley.html"
}
]
menu.go
package main
import(
"fmt"
"encoding/json"
"io/ioutil"
"sort"
"bytes"
)
type MenuItems []MenuItem
func (a MenuItems) Len() int { return len(a) }
func (a MenuItems) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a MenuItems) Less(i, j int) bool { return a[i].Category_id < a[j].Category_id }
type MenuItem struct{
Category_id int `json:"category_id"`
Category_id_400 string `json:"category_id_400"`
Name string `json:"name"`
Parent_id int `json:"parent_id"`
Position int `json:"position"`
Level int `json:"level"`
Status int `json:"status"`
Url string `json:"url"`
Subs []MenuItem `json:"subs"`
}
func (m MenuItem) String() string{
var buffer bytes.Buffer
buffer.WriteString(fmt.Sprintf("%d %s\n",m.Category_id,m.Name))
for _,s := range m.Subs{
buffer.WriteString(fmt.Sprintf(">> %s\n",s.String()));
}
return buffer.String()
//return fmt.Sprintf("CategoryId: %d, ParentId: %d,Name: %s, Sub: %v\n",m.Category_id,m.Parent_id,m.Name,m.Subs);
}
func (m *MenuItem) TryAdd(other MenuItem) bool{
if other.Parent_id == m.Category_id {
m.Subs = append(m.Subs,other);
return true
}else{
for _,sub := range m.Subs{
if found := sub.TryAdd(other);found{
return true
}
}
}
return false
}
func main() {
rootItems := make([]MenuItem,0)
bytes, err := ioutil.ReadFile("menu2.json")
if err != nil{
fmt.Printf("Reading: %s\n",err.Error())
return;
}
var menuItems []MenuItem
err = json.Unmarshal(bytes,&menuItems)
if err != nil{
fmt.Println(err.Error())
return
}
sort.Sort(MenuItems(menuItems))
for _,item := range menuItems{
if item.Parent_id == 2{
rootItems = append(rootItems,item)
}else{
for i:=0;i<len(rootItems);i++{
if found := rootItems[i].TryAdd(item); found{
break;
}else{
fmt.Printf("No Action: Id: %d, Name: %s, Parent: %d.\n",item.Category_id,item.Name,item.Parent_id)
}
}
}
}
fmt.Printf("\nRootitems:\n%s\n",rootItems)
}
输出
Rootitems:
[4 School Supplies
>> 141 School Bags
//第三层应该出现在这里
]
英文:
I have a JSON representing menu items.
A menu item can have a sub menu item, which in turn can have another sub menu item and so son.
The input JSON relates the menu items through a parent id. I'm trying to convert this to a model where each menu item has a slice of its sub menu items.
The sub menus go three levels deep. I've managed to parse upto two levels but I have no idea why the third level isn't being parsed. I've been debugging this problem for hours. I would appreciate some help.
menu2.sjon
[
{
"category_id": 4,
"category_id_400": "'SCHOO",
"name": "School Supplies",
"parent_id": 2,
"position": 2,
"level": 2,
"status": 1,
"url": "http://www.booksrus.kw/sa-en/school-supplies.html"
},
{
"category_id": 141,
"category_id_400": "'SCHBA",
"name": "School Bags",
"parent_id": 4,
"position": 12,
"level": 3,
"status": 1,
"url": "http://www.booksrus.kw/sa-en/school-supplies/school-bags.html"
},
{
"category_id": 269,
"category_id_400": "'AEP",
"name": "Bags Knapsack with Trolley",
"parent_id": 141,
"position": 1,
"level": 4,
"status": 1,
"url": "http://www.booksrus.kw/sa-en/school-supplies/school-bags/bags-knapsack-with-trolley.html"
}
]
menu.go
package main
import(
"fmt"
"encoding/json"
"io/ioutil"
"sort"
"bytes"
)
type MenuItems []MenuItem
func (a MenuItems) Len() int { return len(a) }
func (a MenuItems) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a MenuItems) Less(i, j int) bool { return a[i].Category_id < a[j].Category_id }
type MenuItem struct{
Category_id int `json:"category_id"`
Category_id_400 string `json:"category_id_400"`
Name string `json:"name"`
Parent_id int `json:"parent_id"`
Position int `json:"position"`
Level int `json:"level"`
Status int `json:"status"`
Url string `json:"url"`
Subs []MenuItem `json:"subs"`
}
func (m MenuItem) String() string{
var buffer bytes.Buffer
buffer.WriteString(fmt.Sprintf("%d %s\n",m.Category_id,m.Name))
for _,s := range m.Subs{
buffer.WriteString(fmt.Sprintf("> %s\n",s.String()));
}
return buffer.String()
//return fmt.Sprintf("CategoryId: %d, ParentId: %d,Name: %s, Sub: %v\n",m.Category_id,m.Parent_id,m.Name,m.Subs);
}
func (m *MenuItem) TryAdd(other MenuItem) bool{
if other.Parent_id == m.Category_id {
m.Subs = append(m.Subs,other);
return true
}else{
for _,sub := range m.Subs{
if found := sub.TryAdd(other);found{
return true
}
}
}
return false
}
func main() {
rootItems := make([]MenuItem,0)
bytes, err := ioutil.ReadFile("menu2.json")
if err != nil{
fmt.Printf("Reading: %s\n",err.Error())
return;
}
var menuItems []MenuItem
err = json.Unmarshal(bytes,&menuItems)
if err != nil{
fmt.Println(err.Error())
return
}
sort.Sort(MenuItems(menuItems))
for _,item := range menuItems{
if item.Parent_id == 2{
rootItems = append(rootItems,item)
}else{
for i:=0;i<len(rootItems);i++{
if found := rootItems[i].TryAdd(item); found{
break;
}else{
fmt.Printf("No Action: Id: %d, Name: %s, Parent: %d.\n",item.Category_id,item.Name,item.Parent_id)
}
}
}
}
fmt.Printf("\nRootitems:\n%s\n",rootItems)
}
Output
Rootitems:
[4           School Supplies
> 141           School Bags
//Third level should appear here
]
答案1
得分: 1
TryAdd
函数中的这个循环很可能是你的问题所在:
for _, sub := range m.Subs {
if found := sub.TryAdd(other); found {
return true
}
}
在这个循环中,sub
变量实际上是切片元素的副本。你对副本所做的任何更改都不会持久保存到存储在切片中的元素上。
你可以通过不使用元素的副本,而是通过索引引用它来解决这个问题:
for i := range m.Subs {
if found := m.Subs[i].TryAdd(other); found {
return true
}
}
英文:
This loop in the TryAdd
function is most probably your issue:
for _, sub := range m.Subs {
if found := sub.TryAdd(other); found {
return true
}
}
The sub
variable in this loop is actually a copy of the slice element. Any changes you make there will not persist back to the the element that is stored in the slice.
You should be able to solve this issue by not working with the element's copy, but referencing it by its index instead:
for i := range m.Subs {
if found := m.Subs[i].TryAdd(other); found {
return true
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论