github.com/blueinnovationsgroup/can-go@v0.0.0-20230518195432-d0567cda0028/frame_json.go (about) 1 package can 2 3 import ( 4 "encoding/hex" 5 "encoding/json" 6 "fmt" 7 "strconv" 8 ) 9 10 type jsonFrame struct { 11 ID uint32 `json:"id"` 12 Data *string `json:"data"` 13 Length *uint8 `json:"length"` 14 Extended *bool `json:"extended"` 15 Remote *bool `json:"remote"` 16 } 17 18 // JSON returns the JSON-encoding of f, using hex-encoding for the data. 19 // 20 // Examples: 21 // 22 // {"id":32,"data":"0102030405060708"} 23 // {"id":32,"extended":true,"remote":true,"length":4} 24 func (f Frame) JSON() string { 25 switch { 26 case f.IsRemote && f.IsExtended: 27 return `{"id":` + strconv.Itoa(int(f.ID)) + 28 `,"extended":true,"remote":true,"length":` + 29 strconv.Itoa(int(f.Length)) + `}` 30 case f.IsRemote: 31 return `{"id":` + strconv.Itoa(int(f.ID)) + 32 `,"remote":true,"length":` + 33 strconv.Itoa(int(f.Length)) + `}` 34 case f.IsExtended && f.Length == 0: 35 return `{"id":` + strconv.Itoa(int(f.ID)) + `,"extended":true}` 36 case f.IsExtended: 37 return `{"id":` + strconv.Itoa(int(f.ID)) + 38 `,"data":"` + hex.EncodeToString(f.Data[:f.Length]) + `"` + 39 `,"extended":true}` 40 case f.Length == 0: 41 return `{"id":` + strconv.Itoa(int(f.ID)) + `}` 42 default: 43 return `{"id":` + strconv.Itoa(int(f.ID)) + 44 `,"data":"` + hex.EncodeToString(f.Data[:f.Length]) + `"}` 45 } 46 } 47 48 // MarshalJSON returns the JSON-encoding of f, using hex-encoding for the data. 49 // 50 // See JSON for an example of the JSON schema. 51 func (f Frame) MarshalJSON() ([]byte, error) { 52 return []byte(f.JSON()), nil 53 } 54 55 // UnmarshalJSON sets *f using the provided JSON-encoded values. 56 // 57 // See MarshalJSON for an example of the expected JSON schema. 58 // 59 // The result should be checked with Validate to guard against invalid JSON data. 60 func (f *Frame) UnmarshalJSON(jsonData []byte) error { 61 jf := jsonFrame{} 62 if err := json.Unmarshal(jsonData, &jf); err != nil { 63 return err 64 } 65 if jf.Data != nil { 66 data, err := hex.DecodeString(*jf.Data) 67 if err != nil { 68 return fmt.Errorf("failed to hex-decode CAN data: %v: %w", string(jsonData), err) 69 } 70 f.Data = Data{} 71 copy(f.Data[:], data) 72 f.Length = uint8(len(data)) 73 } else { 74 f.Data = Data{} 75 f.Length = 0 76 } 77 f.ID = jf.ID 78 if jf.Remote != nil { 79 f.IsRemote = *jf.Remote 80 } else { 81 f.IsRemote = false 82 } 83 if f.IsRemote { 84 if jf.Length == nil { 85 return fmt.Errorf("missing length field for remote JSON frame: %v", string(jsonData)) 86 } 87 f.Length = *jf.Length 88 } 89 if jf.Extended != nil { 90 f.IsExtended = *jf.Extended 91 } else { 92 f.IsExtended = false 93 } 94 return nil 95 }