Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent alphabetically ordering json at Marshal

I want to prevent alphabetically reordering at Marshal. My script is below. {"key3": "value3", "key2": "value2", "key1": "value1"} is reordered to {"key1":"value1","key2":"value2","key3":"value3"} by Marshal. I thought this may be close issue. But I could not solve my issue. Is there way to solve this?

Script

package main

import (
    "encoding/json"
    "fmt"
)

func main() {
    obj := `{"key3": "value3", "key2": "value2", "key1": "value1"}`
    var o map[string]interface{}
    json.Unmarshal([]byte(obj), &o)
    fmt.Println(o)
    r, _ := json.Marshal(o)
    fmt.Println(string(r))
}

play.golang.org

  • fmt.Println(o) is map[key3:value3 key2:value2 key1:value1].
  • fmt.Println(string(r)) is {"key1":"value1","key2":"value2","key3":"value3"}.

Thank you so much for your time. And I'm sorry for my immature question.

like image 231
Elsa Avatar asked Jan 17 '18 03:01

Elsa


1 Answers

You can preserve the order like this:

type OrderedMap struct {
    Order []string
    Map map[string]string
}

func (om *OrderedMap) UnmarshalJSON(b []byte) error {
    json.Unmarshal(b,&om.Map)

    index:=make(map[string]int)
    for key:=range om.Map {
        om.Order=append(om.Order,key)
        esc,_:=json.Marshal(key) //Escape the key
        index[key]=bytes.Index(b,esc)
    }

    sort.Slice(om.Order, func(i,j int) bool { return index[om.Order[i]]<index[om.Order[j]] })
    return nil
}

func (om OrderedMap) MarshalJSON() ([]byte, error) {
    var b []byte
    buf:=bytes.NewBuffer(b)
    buf.WriteRune('{')
    l:=len(om.Order)
    for i,key:=range om.Order {
        km,err:=json.Marshal(key)
        if err!=nil { return nil,err }
        buf.Write(km)
        buf.WriteRune(':')
        vm,err:=json.Marshal(om.Map[key])
        if err!=nil { return nil,err }
        buf.Write(vm)
        if i!=l-1 { buf.WriteRune(',') }
        fmt.Println(buf.String())
    }
    buf.WriteRune('}')
    fmt.Println(buf.String())
    return buf.Bytes(),nil
}

Playground: https://play.golang.org/p/TxenZEuy_u0

Please note that json spec says objects are unordered, which means other client may not respect the order you preserve.

like image 130
leaf bebop Avatar answered Oct 23 '22 15:10

leaf bebop