github.com/pingcap/br@v5.3.0-alpha.0.20220125034240-ec59c7b6ce30+incompatible/pkg/utils/json.go (about) 1 package utils 2 3 import ( 4 "encoding/hex" 5 "encoding/json" 6 7 "github.com/pingcap/errors" 8 9 backuppb "github.com/pingcap/kvproto/pkg/backup" 10 ) 11 12 // MarshalBackupMeta converts the backupmeta strcture to JSON. 13 // Unlike json.Marshal, this function also format some []byte fields for human reading. 14 func MarshalBackupMeta(meta *backuppb.BackupMeta) ([]byte, error) { 15 result, err := makeJSONBackupMeta(meta) 16 if err != nil { 17 return nil, err 18 } 19 return json.Marshal(result) 20 } 21 22 // UnmarshalBackupMeta converts the prettied JSON format of backupmeta 23 // (made by MarshalBackupMeta) back to the go structure. 24 func UnmarshalBackupMeta(data []byte) (*backuppb.BackupMeta, error) { 25 jMeta := &jsonBackupMeta{} 26 if err := json.Unmarshal(data, jMeta); err != nil { 27 return nil, errors.Trace(err) 28 } 29 return fromJSONBackupMeta(jMeta) 30 } 31 32 type jsonValue interface{} 33 34 type jsonFile struct { 35 SHA256 string `json:"sha256,omitempty"` 36 StartKey string `json:"start_key,omitempty"` 37 EndKey string `json:"end_key,omitempty"` 38 *backuppb.File 39 } 40 41 func makeJSONFile(file *backuppb.File) *jsonFile { 42 return &jsonFile{ 43 SHA256: hex.EncodeToString(file.Sha256), 44 StartKey: hex.EncodeToString(file.StartKey), 45 EndKey: hex.EncodeToString(file.EndKey), 46 File: file, 47 } 48 } 49 50 func fromJSONFile(jFile *jsonFile) (*backuppb.File, error) { 51 f := jFile.File 52 var err error 53 f.Sha256, err = hex.DecodeString(jFile.SHA256) 54 if err != nil { 55 return nil, errors.Trace(err) 56 } 57 f.StartKey, err = hex.DecodeString(jFile.StartKey) 58 if err != nil { 59 return nil, errors.Trace(err) 60 } 61 f.EndKey, err = hex.DecodeString(jFile.EndKey) 62 if err != nil { 63 return nil, errors.Trace(err) 64 } 65 return f, nil 66 } 67 68 type jsonRawRange struct { 69 StartKey string `json:"start_key,omitempty"` 70 EndKey string `json:"end_key,omitempty"` 71 *backuppb.RawRange 72 } 73 74 func makeJSONRawRange(raw *backuppb.RawRange) *jsonRawRange { 75 return &jsonRawRange{ 76 StartKey: hex.EncodeToString(raw.StartKey), 77 EndKey: hex.EncodeToString(raw.EndKey), 78 RawRange: raw, 79 } 80 } 81 82 func fromJSONRawRange(rng *jsonRawRange) (*backuppb.RawRange, error) { 83 r := rng.RawRange 84 var err error 85 r.StartKey, err = hex.DecodeString(rng.StartKey) 86 if err != nil { 87 return nil, errors.Trace(err) 88 } 89 r.EndKey, err = hex.DecodeString(rng.EndKey) 90 if err != nil { 91 return nil, errors.Trace(err) 92 } 93 return r, nil 94 } 95 96 type jsonSchema struct { 97 Table jsonValue `json:"table,omitempty"` 98 DB jsonValue `json:"db,omitempty"` 99 *backuppb.Schema 100 } 101 102 func makeJSONSchema(schema *backuppb.Schema) (*jsonSchema, error) { 103 result := &jsonSchema{Schema: schema} 104 if err := json.Unmarshal(schema.Db, &result.DB); err != nil { 105 return nil, errors.Trace(err) 106 } 107 if err := json.Unmarshal(schema.Table, &result.Table); err != nil { 108 return nil, errors.Trace(err) 109 } 110 return result, nil 111 } 112 113 func fromJSONSchema(jSchema *jsonSchema) (*backuppb.Schema, error) { 114 schema := jSchema.Schema 115 var err error 116 schema.Db, err = json.Marshal(jSchema.DB) 117 if err != nil { 118 return nil, errors.Trace(err) 119 } 120 schema.Table, err = json.Marshal(jSchema.Table) 121 if err != nil { 122 return nil, errors.Trace(err) 123 } 124 return schema, nil 125 } 126 127 type jsonBackupMeta struct { 128 Files []*jsonFile `json:"files,omitempty"` 129 RawRanges []*jsonRawRange `json:"raw_ranges,omitempty"` 130 Schemas []*jsonSchema `json:"schemas,omitempty"` 131 DDLs jsonValue `json:"ddls,omitempty"` 132 133 *backuppb.BackupMeta 134 } 135 136 func makeJSONBackupMeta(meta *backuppb.BackupMeta) (*jsonBackupMeta, error) { 137 result := &jsonBackupMeta{ 138 BackupMeta: meta, 139 } 140 for _, file := range meta.Files { 141 result.Files = append(result.Files, makeJSONFile(file)) 142 } 143 for _, rawRange := range meta.RawRanges { 144 result.RawRanges = append(result.RawRanges, makeJSONRawRange(rawRange)) 145 } 146 for _, schema := range meta.Schemas { 147 s, err := makeJSONSchema(schema) 148 if err != nil { 149 return nil, err 150 } 151 result.Schemas = append(result.Schemas, s) 152 } 153 if err := json.Unmarshal(meta.Ddls, &result.DDLs); err != nil { 154 return nil, errors.Trace(err) 155 } 156 return result, nil 157 } 158 159 func fromJSONBackupMeta(jMeta *jsonBackupMeta) (*backuppb.BackupMeta, error) { 160 meta := jMeta.BackupMeta 161 for _, schema := range jMeta.Schemas { 162 s, err := fromJSONSchema(schema) 163 if err != nil { 164 return nil, err 165 } 166 meta.Schemas = append(meta.Schemas, s) 167 } 168 for _, file := range jMeta.Files { 169 f, err := fromJSONFile(file) 170 if err != nil { 171 return nil, err 172 } 173 meta.Files = append(meta.Files, f) 174 } 175 for _, rawRange := range jMeta.RawRanges { 176 rng, err := fromJSONRawRange(rawRange) 177 if err != nil { 178 return nil, err 179 } 180 meta.RawRanges = append(meta.RawRanges, rng) 181 } 182 var err error 183 meta.Ddls, err = json.Marshal(jMeta.DDLs) 184 if err != nil { 185 return nil, errors.Trace(err) 186 } 187 return meta, nil 188 }