github.com/isyscore/isc-gobase@v1.5.3-0.20231218061332-cbc7451899e9/isc/yaml.go (about) 1 package isc 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "log" 7 "reflect" 8 "regexp" 9 "sort" 10 "strconv" 11 "strings" 12 13 "gopkg.in/yaml.v2" 14 ) 15 16 /** 17 * 1.yaml <---> properties 18 * 2.yaml <---> json 19 * 3.yaml <---> map 20 * 4.yaml <---> list 21 * 5.yaml <---> kvList 22 */ 23 24 // NewLine 换行符 25 var NewLine = "\n" 26 27 // IndentBlanks 缩进空格 28 var IndentBlanks = " " 29 30 // SignSemicolon 分号连接符 31 var SignSemicolon = ":" 32 33 // SignEqual 等号连接符 34 var SignEqual = "=" 35 36 // Dot 点 37 var Dot = "." 38 39 // ArrayBlanks 数组缩进 40 var ArrayBlanks = "- " 41 42 // YamlNewLineDom yaml的value换行符 43 var YamlNewLineDom = "|\n" 44 45 var rangePattern = regexp.MustCompile("^(.*)\\[(\\d*)\\]$") 46 47 type TypeEnum int8 48 49 const ( 50 TeYAML TypeEnum = 0 51 TePROPERTIES TypeEnum = 1 52 TeJSON TypeEnum = 2 53 TeSTRING TypeEnum = 3 54 ) 55 56 type Properties struct { 57 Value map[string]string 58 } 59 60 type StringPair struct { 61 Left string 62 Right string 63 } 64 65 type ConvertError struct { 66 errMsg string 67 } 68 69 func (convertError *ConvertError) Error() string { 70 return convertError.errMsg 71 } 72 73 func IsYaml(content string) bool { 74 if !strings.Contains(content, ":") && !strings.Contains(content, "-") { 75 return false 76 } 77 78 _, err := YamlToProperties(content) 79 if err != nil { 80 return false 81 } 82 return true 83 } 84 85 func IsProperty(content string) bool { 86 if !strings.Contains(content, "=") { 87 return false 88 } 89 90 yml, _ := PropertiesToYaml(content) 91 _, err := YamlToProperties(yml) 92 if err != nil { 93 return false 94 } 95 return true 96 } 97 98 func IsJson(content string) bool { 99 if !strings.HasPrefix(content, "{") && !strings.HasPrefix(content, "[") { 100 return false 101 } 102 103 var object any 104 err := json.Unmarshal([]byte(content), &object) 105 if err != nil { 106 return false 107 } 108 return true 109 } 110 111 func YamlToProperties(contentOfYaml string) (string, error) { 112 // yaml 到 map 113 dataMap, err := YamlToMap(contentOfYaml) 114 if err != nil { 115 return "", err 116 } 117 118 return MapToProperties(dataMap) 119 } 120 121 func YamlToPropertiesWithKey(key string, contentOfYaml string) (string, error) { 122 if "" == key { 123 return "", &ConvertError{errMsg: "key is nil"} 124 } 125 if "" == contentOfYaml { 126 return key + "=\"\"", nil 127 } 128 if !strings.Contains(contentOfYaml, ":") && !strings.Contains(contentOfYaml, "-") { 129 return "", &ConvertError{errMsg: "content is illegal for yaml"} 130 } 131 132 contentOfYaml = strings.TrimSpace(contentOfYaml) 133 if strings.HasPrefix(contentOfYaml, "-") { 134 dataMap := make(map[string]any) 135 kvList, err := YamlToList(contentOfYaml) 136 if err != nil { 137 log.Printf("YamlToPropertiesWithKey error: %v, content: %v", err, contentOfYaml) 138 return "", err 139 } 140 141 dataMap[key] = kvList 142 yamlStr, err := ObjectToYaml(dataMap) 143 if err != nil { 144 return "", err 145 } 146 return YamlToProperties(yamlStr) 147 } 148 149 property, err := YamlToProperties(contentOfYaml) 150 if err != nil { 151 log.Printf("YamlToPropertiesWithKey error: %v, content: %v", err, contentOfYaml) 152 return "", err 153 } 154 155 return propertiesAppendPrefixKey(key, property) 156 } 157 158 func JsonToMap(contentOfJson string) (map[string]any, error) { 159 if contentOfJson == "" || (!strings.HasPrefix(contentOfJson, "{") && !strings.HasPrefix(contentOfJson, "[")) { 160 return nil, &ChangeError{ErrMsg: "不符合json格式"} 161 } 162 resultMap := make(map[string]any) 163 err := json.Unmarshal([]byte(contentOfJson), &resultMap) 164 if err != nil { 165 log.Printf("JsonToMap, error: %v, content: %v", err, contentOfJson) 166 return nil, err 167 } 168 169 return resultMap, nil 170 } 171 172 func YamlToMap(contentOfYaml string) (map[string]any, error) { 173 resultMap := make(map[string]any) 174 err := yaml.Unmarshal([]byte(contentOfYaml), &resultMap) 175 if err != nil { 176 log.Printf("YamlToMap, error: %v, content: %v", err, contentOfYaml) 177 return nil, err 178 } 179 180 return resultMap, nil 181 } 182 183 func YamlToJson(contentOfYaml string) (string, error) { 184 if contentOfYaml != "-" && strings.Contains(contentOfYaml, ":") { 185 return "", &ConvertError{errMsg: "the content is invalidate for json"} 186 } 187 188 var data any 189 err := yaml.Unmarshal([]byte(contentOfYaml), &data) 190 if err != nil { 191 log.Printf("YamlToList, error: %v, content: %v", err, contentOfYaml) 192 return "", err 193 } 194 195 jsonStr, err := json.Marshal(data) 196 if err != nil { 197 return "", err 198 } 199 return string(jsonStr), nil 200 } 201 202 func YamlToKvList(contentOfYaml string) ([]StringPair, error) { 203 if !strings.Contains(contentOfYaml, ":") && !strings.Contains(contentOfYaml, "-") { 204 return nil, nil 205 } 206 207 property, err := YamlToProperties(contentOfYaml) 208 if err != nil { 209 return nil, err 210 } 211 212 propertiesLineWordList := GetPropertiesItemLineList(property) 213 var pairs []StringPair 214 for _, element := range propertiesLineWordList { 215 element = strings.TrimSpace(element) 216 if "" == element { 217 continue 218 } 219 values := strings.SplitN(element, SignEqual, 2) 220 pairs = append(pairs, StringPair{Left: values[0], Right: values[1]}) 221 } 222 223 return pairs, nil 224 } 225 226 func YamlToList(contentOfYaml string) ([]any, error) { 227 if !strings.HasPrefix(strings.TrimSpace(contentOfYaml), "-") { 228 return []any{}, &ConvertError{errMsg: "the content of yaml not start with '-'"} 229 } 230 var resultList []any 231 err := yaml.Unmarshal([]byte(contentOfYaml), &resultList) 232 if err != nil { 233 log.Printf("YamlToList, error: %v, content: %v", err, contentOfYaml) 234 return nil, err 235 } 236 237 return resultList, nil 238 } 239 240 func YamlCheck(content string) error { 241 if "" == content { 242 return &ConvertError{errMsg: "yaml is empty"} 243 } 244 245 if !strings.Contains(content, ":") && !strings.Contains(content, "-") { 246 return &ConvertError{errMsg: "yaml content does not contain ':' nor '-'"} 247 } 248 249 if strings.Contains(content, "---\n") { 250 return &ConvertError{errMsg: "yaml not support import for content of '---'"} 251 } 252 253 _, err := YamlToProperties(content) 254 if err != nil { 255 return err 256 } 257 return nil 258 } 259 260 func PropertiesToMap(contentOfProperties string) (map[string]any, error) { 261 if !strings.Contains(contentOfProperties, "=") { 262 return nil, &ConvertError{errMsg: "the content is illegal for properties"} 263 } 264 265 var keyChangeMap = make(map[string]string) 266 var resultMap = make(map[string]any) 267 propertiesLineWordList := GetPropertiesItemLineList(contentOfProperties) 268 for _, line := range propertiesLineWordList { 269 line = strings.TrimSpace(line) 270 if "" == line { 271 continue 272 } 273 274 lineKVs := strings.SplitN(line, "=", 2) 275 key := lineKVs[0] 276 value := lineKVs[1] 277 278 if strings.Contains(value, "\n") { 279 value = YamlNewLineDom + value 280 } 281 282 if strings.HasPrefix(value, "${") && strings.HasSuffix(value, "}") { 283 // 记录两个key,原始key和替代key 284 keyChangeMap[key] = value[2:len(value)-1] 285 continue 286 } 287 resultMap[key] = value 288 } 289 290 // 将两个key进行替换 291 for keyOriginal, keyNewChange := range keyChangeMap { 292 if value, exist := resultMap[keyNewChange]; exist { 293 resultMap[keyOriginal] = value 294 } 295 } 296 return resultMap, nil 297 } 298 299 func propertiesAppendPrefixKey(key string, propertiesContent string) (string, error) { 300 itemLines := GetPropertiesItemLineList(propertiesContent) 301 var datas []string 302 for _, line := range itemLines { 303 if !strings.Contains(line, SignEqual) { 304 continue 305 } 306 307 kvs := strings.SplitN(line, SignEqual, 2) 308 datas = append(datas, key+Dot+kvs[0]+SignEqual+kvs[1]) 309 } 310 311 return strings.Join(datas, NewLine), nil 312 } 313 314 func deepPut(dataMap map[string]any, key string, value any) map[string]any { 315 mapValue, exist := dataMap[key] 316 if !exist { 317 dataMap[key] = value 318 } else { 319 if reflect.Map == reflect.TypeOf(value).Kind() { 320 leftMap := mapValue.(map[string]any) 321 rightMap := value.(map[string]any) 322 323 for rightMapKey := range rightMap { 324 leftMap = deepPut(leftMap, rightMapKey, rightMap[rightMapKey]) 325 } 326 dataMap[key] = leftMap 327 } 328 } 329 330 return dataMap 331 } 332 333 func PropertiesToYaml(contentOfProperties string) (string, error) { 334 var yamlLineList []string 335 var yamlNodes []YamlNode 336 propertiesLineWordList := GetPropertiesItemLineList(contentOfProperties) 337 for _, line := range propertiesLineWordList { 338 line = strings.TrimSpace(line) 339 if line != "" { 340 // 注释数据不要 341 if strings.HasPrefix(line, "#") { 342 continue 343 } 344 345 index := strings.Index(line, SignEqual) 346 if index > -1 { 347 key := line[:index] 348 value := line[index+1:] 349 350 if strings.Contains(value, "\n") { 351 value = YamlNewLineDom + value 352 } 353 354 lineWordList := strings.Split(key, ".") 355 lineWordList, yamlNodes = wordToNode(lineWordList, yamlNodes, nil, false, -1, appendSpaceForArrayValue(value)) 356 } 357 } 358 } 359 yamlLineList = formatPropertiesToYaml(yamlLineList, yamlNodes, false, "") 360 return strings.Join(yamlLineList, "\n") + "\n", nil 361 } 362 363 func ObjectToYaml(value any) (string, error) { 364 bytes2, err := yaml.Marshal(value) 365 if err != nil { 366 log.Printf("ObjectToYaml error: %v, content: %v", err, value) 367 return "", &ConvertError{errMsg: "ObjectToYaml error"} 368 } 369 return string(bytes2), nil 370 } 371 372 // MapToProperties 进行深层嵌套的map数据处理 373 func MapToProperties(dataMap map[string]any) (string, error) { 374 var propertyStrList []string 375 for key, value := range dataMap { 376 if value == nil { 377 continue 378 } 379 valueKind := reflect.TypeOf(value).Kind() 380 switch valueKind { 381 case reflect.Map: 382 { 383 propertyStrList = doMapToProperties(propertyStrList, value, prefixWithDOT("")+key) 384 } 385 case reflect.Array, reflect.Slice: 386 { 387 objectValue := reflect.ValueOf(value) 388 for index := 0; index < objectValue.Len(); index++ { 389 propertyStrList = doMapToProperties(propertyStrList, objectValue.Index(index).Interface(), prefixWithDOT("")+key+"["+strconv.Itoa(index)+"]") 390 } 391 } 392 case reflect.String: 393 objectValue := reflect.ValueOf(value) 394 objectValueStr := strings.ReplaceAll(objectValue.String(), "\n", "\\\n") 395 propertyStrList = append(propertyStrList, prefixWithDOT("")+key+SignEqual+objectValueStr) 396 default: 397 propertyStrList = append(propertyStrList, prefixWithDOT("")+key+SignEqual+fmt.Sprintf("%v", value)) 398 } 399 } 400 resultStr := "" 401 for _, propertyStr := range propertyStrList { 402 resultStr += propertyStr + "\n" 403 } 404 405 return resultStr, nil 406 } 407 408 func KvToProperties(key, value string, valueType TypeEnum) (string, error) { 409 switch valueType { 410 case TeYAML: 411 return YamlToPropertiesWithKey(key, value) 412 case TeJSON: 413 value, err := JsonToYaml(value) 414 if err != nil { 415 return "", err 416 } 417 return YamlToPropertiesWithKey(key, value) 418 case TePROPERTIES: 419 return propertiesAppendPrefixKey(key, value) 420 case TeSTRING: 421 return key + "=" + appendSpaceForArrayValue(value), nil 422 default: 423 break 424 } 425 return "", nil 426 } 427 428 func JsonToYaml(contentOfJson string) (string, error) { 429 if !strings.HasPrefix(contentOfJson, "{") && !strings.HasPrefix(contentOfJson, "[") { 430 return "", &ConvertError{errMsg: "content is not json"} 431 } 432 433 if "[]" == contentOfJson { 434 return "", nil 435 } 436 437 // go中的json转换不识别"'"字符,因此这里将其转换为"""这种字符 438 contentOfJsonTem := strings.ReplaceAll(contentOfJson, "'", "\"") 439 440 var object any 441 err := json.Unmarshal([]byte(contentOfJsonTem), &object) 442 if err != nil { 443 return "", err 444 } 445 446 return ObjectToYaml(object) 447 } 448 449 func PropertiesEntityToYaml(properties Properties) (string, error) { 450 if properties.Value == nil { 451 return "", &ConvertError{"PropertiesEntityToYaml value is empty"} 452 } 453 454 var content = "" 455 for key, value := range properties.Value { 456 content += key + "=" + value + "\n" 457 } 458 return PropertiesToYaml(content) 459 } 460 461 func GetPropertiesItemLineList(content string) []string { 462 if "" == content { 463 return []string{} 464 } 465 466 lineList := strings.Split(content, NewLine) 467 var itemLineList []string 468 var stringAppender string 469 for _, line := range lineList { 470 if strings.HasSuffix(content, "\\") { 471 stringAppender += line + "\n" 472 } else { 473 stringAppender += line 474 itemLineList = append(itemLineList, stringAppender) 475 stringAppender = "" 476 } 477 } 478 return itemLineList 479 } 480 481 func formatPropertiesToYaml(yamlLineList []string, yamlNodes []YamlNode, lastNodeArrayFlag bool, blanks string) []string { 482 var beforeNodeIndex = -1 483 var equalSign string 484 485 for _, yamlNode := range yamlNodes { 486 value := yamlNode.value 487 488 equalSign = SignSemicolon 489 if "" != value { 490 equalSign = SignSemicolon + " " 491 } 492 493 yamlNode.resortValue() 494 495 name := yamlNode.name 496 if lastNodeArrayFlag { 497 if "" == name { 498 yamlLineList = append(yamlLineList, blanks+ArrayBlanks+stringValueWrap(value)) 499 } else { 500 if -1 != beforeNodeIndex && beforeNodeIndex == yamlNode.lastNodeIndex { 501 yamlLineList = append(yamlLineList, blanks+IndentBlanks+name+equalSign+stringValueWrap(value)) 502 } else { 503 yamlLineList = append(yamlLineList, blanks+ArrayBlanks+name+equalSign+stringValueWrap(value)) 504 } 505 } 506 beforeNodeIndex = yamlNode.lastNodeIndex 507 } else { 508 yamlLineList = append(yamlLineList, blanks+name+equalSign+stringValueWrap(value)) 509 } 510 511 if yamlNode.arrayFlag { 512 if lastNodeArrayFlag { 513 yamlLineList = formatPropertiesToYaml(yamlLineList, yamlNode.valueList, true, IndentBlanks+IndentBlanks+blanks) 514 } else { 515 yamlLineList = formatPropertiesToYaml(yamlLineList, yamlNode.valueList, true, IndentBlanks+blanks) 516 } 517 } else { 518 if lastNodeArrayFlag { 519 yamlLineList = formatPropertiesToYaml(yamlLineList, yamlNode.children, false, IndentBlanks+IndentBlanks+blanks) 520 } else { 521 yamlLineList = formatPropertiesToYaml(yamlLineList, yamlNode.children, false, IndentBlanks+blanks) 522 } 523 } 524 } 525 return yamlLineList 526 } 527 528 func wordToNode(lineWordList []string, nodeList []YamlNode, parentNode *YamlNode, lastNodeArrayFlag bool, index int, value string) ([]string, []YamlNode) { 529 if len(lineWordList) == 0 { 530 if lastNodeArrayFlag { 531 node := YamlNode{value: value, lastNodeIndex: -1} 532 nodeList = append(nodeList, node) 533 } 534 } else { 535 nodeName := lineWordList[0] 536 nodeName, nextIndex := peelArray(nodeName) 537 538 var node YamlNode 539 if nil != parentNode { 540 node = YamlNode{name: nodeName, parent: parentNode, lastNodeIndex: index} 541 } else { 542 node = YamlNode{name: nodeName, lastNodeIndex: index} 543 } 544 lineWordList = lineWordList[1:] 545 546 //如果节点下面的子节点数量为0,则为终端节点,也就是赋值节点 547 if len(lineWordList) == 0 { 548 if -1 == nextIndex { 549 node.value = value 550 } 551 } 552 553 // nextIndex 不空,表示当前节点为数组,则之后的数据为他的节点数据 554 if nextIndex != -1 { 555 node.arrayFlag = true 556 var hasEqualsName = false 557 558 //遍历查询节点是否存在 559 for innerIndex := range nodeList { 560 //如果节点名称已存在,则递归添加剩下的数据节点 561 if nodeName == nodeList[innerIndex].name && nodeList[innerIndex].arrayFlag { 562 yamlNodeIndex := nodeList[innerIndex].lastNodeIndex 563 if -1 == yamlNodeIndex || index == yamlNodeIndex { 564 hasEqualsName = true 565 lineWordList, nodeList[innerIndex].valueList = wordToNode(lineWordList, nodeList[innerIndex].valueList, node.parent, true, nextIndex, appendSpaceForArrayValue(value)) 566 } 567 } 568 } 569 570 //如果遍历结果为节点名称不存在,则递归添加剩下的数据节点,并把新节点添加到上级yamlTree的子节点中 571 if !hasEqualsName { 572 lineWordList, node.valueList = wordToNode(lineWordList, node.valueList, node.parent, true, nextIndex, appendSpaceForArrayValue(value)) 573 nodeList = append(nodeList, node) 574 } 575 } else { 576 var hasEqualsName = false 577 for innerIndex := range nodeList { 578 if !lastNodeArrayFlag { 579 //如果节点名称已存在,则递归添加剩下的数据节点 580 if nodeName == nodeList[innerIndex].name { 581 hasEqualsName = true 582 lineWordList, nodeList[innerIndex].children = wordToNode(lineWordList, nodeList[innerIndex].children, &nodeList[innerIndex], false, nextIndex, appendSpaceForArrayValue(value)) 583 } 584 } else { 585 //如果节点名称已存在,则递归添加剩下的数据节点 586 if nodeName == nodeList[innerIndex].name { 587 yamlNodeIndex := nodeList[innerIndex].lastNodeIndex 588 if -1 == yamlNodeIndex || index == yamlNodeIndex { 589 hasEqualsName = true 590 lineWordList, nodeList[innerIndex].children = wordToNode(lineWordList, nodeList[innerIndex].children, &nodeList[innerIndex], true, nextIndex, appendSpaceForArrayValue(value)) 591 } 592 } 593 } 594 } 595 596 //如果遍历结果为节点名称不存在,则递归添加剩下的数据节点,并把新节点添加到上级yamlTree的子节点中 597 if !hasEqualsName { 598 lineWordList, node.children = wordToNode(lineWordList, node.children, &node, false, nextIndex, appendSpaceForArrayValue(value)) 599 nodeList = append(nodeList, node) 600 } 601 } 602 } 603 return lineWordList, nodeList 604 } 605 606 func doMapToProperties(propertyStrList []string, value any, prefix string) []string { 607 if value == nil { 608 return propertyStrList 609 } 610 valueKind := reflect.TypeOf(value).Kind() 611 switch valueKind { 612 case reflect.Map: 613 { 614 // map结构 615 if reflect.ValueOf(value).Len() == 0 { 616 return propertyStrList 617 } 618 619 for mapR := reflect.ValueOf(value).MapRange(); mapR.Next(); { 620 mapKey := mapR.Key().Interface() 621 mapValue := mapR.Value().Interface() 622 propertyStrList = doMapToProperties(propertyStrList, mapValue, prefixWithDOT(prefix)+fmt.Sprintf("%v", mapKey)) 623 } 624 } 625 case reflect.Array, reflect.Slice: 626 { 627 objectValue := reflect.ValueOf(value) 628 for index := 0; index < objectValue.Len(); index++ { 629 propertyStrList = doMapToProperties(propertyStrList, objectValue.Index(index).Interface(), prefix+"["+strconv.Itoa(index)+"]") 630 } 631 } 632 case reflect.String: 633 objectValue := reflect.ValueOf(value) 634 objectValueStr := strings.ReplaceAll(objectValue.String(), "\n", "\\\n") 635 propertyStrList = append(propertyStrList, prefix+SignEqual+objectValueStr) 636 default: 637 objectValue := fmt.Sprintf("%v", reflect.ValueOf(value)) 638 propertyStrList = append(propertyStrList, prefix+SignEqual+objectValue) 639 } 640 return propertyStrList 641 } 642 643 func prefixWithDOT(prefix string) string { 644 if "" == prefix { 645 return "" 646 } 647 return prefix + "." 648 } 649 650 func peelArray(nodeName string) (string, int) { 651 var index = -1 652 var name = nodeName 653 var err error 654 655 subData := rangePattern.FindAllStringSubmatch(nodeName, -1) 656 if len(subData) > 0 { 657 name = subData[0][1] 658 indexStr := subData[0][2] 659 if "" != indexStr { 660 index, err = strconv.Atoi(indexStr) 661 if err != nil { 662 log.Printf("解析错误, nodeName=" + nodeName) 663 return "", -1 664 } 665 } 666 } 667 return name, index 668 } 669 670 // 671 // 将yaml对应的这种value进行添加前缀空格,其中value为key1对应的value 672 // test: 673 // key1: | 674 // value1 675 // value2 676 // value3 677 // 对应的值 678 // {@code 679 // | 680 // value1 681 // value2 682 // value3 683 // } 684 // 685 // @param Value 待转换的值比如{@code 686 // test: 687 // key1: | 688 // value1 689 // value2 690 // value3 691 // } 692 // @return 添加前缀空格之后的处理 693 // {@code 694 // | 695 // value1 696 // value2 697 // value3 698 // } 699 // 700 func appendSpaceForArrayValue(value string) string { 701 if !strings.HasPrefix(value, YamlNewLineDom) { 702 return value 703 } 704 705 value = value[len(YamlNewLineDom):] 706 valueTems := strings.Split(value, "\\n") 707 708 var strs []string 709 for _, element := range valueTems { 710 tem := element 711 if strings.HasSuffix(element, "\\") { 712 tem = element[:len(element)-1] 713 } 714 strs = append(strs, IndentBlanks+tem) 715 } 716 return YamlNewLineDom + strings.Join(strs, "\n") 717 } 718 719 func stringValueWrap(value string) string { 720 if "" == value { 721 return "" 722 } 723 // 对数组的数据进行特殊处理 724 if strings.HasPrefix(value, "[") && strings.HasSuffix(value, "]") { 725 return "'" + value + "'" 726 } 727 return value 728 } 729 730 type YamlNode struct { 731 732 // 父节点 733 parent *YamlNode 734 735 // 只有parent为null时候,该值才可能有值 736 projectRemark string 737 738 // name 739 name string 740 741 // value 742 value string 743 744 // 子节点 745 children []YamlNode 746 747 // 数组标示 748 arrayFlag bool 749 750 // 存储的数组中的前一个节点的下标 751 lastNodeIndex int 752 753 // 只有数组标示为true,下面的value才有值 754 valueList []YamlNode 755 } 756 757 func (yamlNode *YamlNode) resortValue() { 758 if !yamlNode.arrayFlag || len(yamlNode.valueList) == 0 { 759 return 760 } 761 762 sort.Slice(yamlNode.valueList, func(i, j int) bool { 763 a := yamlNode.valueList[i] 764 b := yamlNode.valueList[j] 765 766 if -1 == a.lastNodeIndex || -1 == b.lastNodeIndex { 767 return false 768 } 769 return a.lastNodeIndex < b.lastNodeIndex 770 }) 771 772 for _, node := range yamlNode.valueList { 773 node.resortValue() 774 } 775 }