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  }