| // Copyright ©2018 The Gonum Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Package sigmajs implements marshaling and unmarshaling of Sigma.js JSON documents. |
| // |
| // See http://sigmajs.org/ for Sigma.js documentation. |
| package sigmajs // import "gonum.org/v1/gonum/graph/formats/sigmajs" |
| |
| import ( |
| "encoding/json" |
| "errors" |
| "fmt" |
| ) |
| |
| // Graph is a Sigma.js graph. |
| type Graph struct { |
| Nodes []Node `json:"nodes"` |
| Edges []Edge `json:"edges"` |
| } |
| |
| // Node is a Sigma.js node. |
| type Node struct { |
| ID string |
| Attributes map[string]interface{} |
| } |
| |
| var ( |
| _ json.Marshaler = (*Node)(nil) |
| _ json.Unmarshaler = (*Node)(nil) |
| ) |
| |
| // MarshalJSON implements the json.Marshaler interface. |
| func (n *Node) MarshalJSON() ([]byte, error) { |
| if n.Attributes == nil { |
| type node struct { |
| ID string `json:"id"` |
| } |
| return json.Marshal(node{ID: n.ID}) |
| } |
| n.Attributes["id"] = n.ID |
| b, err := json.Marshal(n.Attributes) |
| delete(n.Attributes, "id") |
| return b, err |
| } |
| |
| // UnmarshalJSON implements the json.Unmarshaler interface. |
| func (n *Node) UnmarshalJSON(data []byte) error { |
| var attrs map[string]interface{} |
| err := json.Unmarshal(data, &attrs) |
| if err != nil { |
| return err |
| } |
| id, ok := attrs["id"] |
| if !ok { |
| return errors.New("sigmajs: no ID") |
| } |
| n.ID = fmt.Sprint(id) |
| delete(attrs, "id") |
| if len(attrs) != 0 { |
| n.Attributes = attrs |
| } |
| return nil |
| } |
| |
| // Edge is a Sigma.js edge. |
| type Edge struct { |
| ID string |
| Source string |
| Target string |
| Attributes map[string]interface{} |
| } |
| |
| var ( |
| _ json.Marshaler = (*Edge)(nil) |
| _ json.Unmarshaler = (*Edge)(nil) |
| ) |
| |
| // MarshalJSON implements the json.Marshaler interface. |
| func (e *Edge) MarshalJSON() ([]byte, error) { |
| if e.Attributes == nil { |
| type edge struct { |
| ID string `json:"id"` |
| Source string `json:"source"` |
| Target string `json:"target"` |
| } |
| return json.Marshal(edge{ID: e.ID, Source: e.Source, Target: e.Target}) |
| } |
| e.Attributes["id"] = e.ID |
| e.Attributes["source"] = e.Source |
| e.Attributes["target"] = e.Target |
| b, err := json.Marshal(e.Attributes) |
| delete(e.Attributes, "id") |
| delete(e.Attributes, "source") |
| delete(e.Attributes, "target") |
| return b, err |
| } |
| |
| // UnmarshalJSON implements the json.Unmarshaler interface. |
| func (e *Edge) UnmarshalJSON(data []byte) error { |
| var attrs map[string]interface{} |
| err := json.Unmarshal(data, &attrs) |
| if err != nil { |
| return err |
| } |
| id, ok := attrs["id"] |
| if !ok { |
| return errors.New("sigmajs: no ID") |
| } |
| source, ok := attrs["source"] |
| if !ok { |
| return errors.New("sigmajs: no source") |
| } |
| target, ok := attrs["target"] |
| if !ok { |
| return errors.New("sigmajs: no target") |
| } |
| e.ID = fmt.Sprint(id) |
| e.Source = fmt.Sprint(source) |
| e.Target = fmt.Sprint(target) |
| delete(attrs, "id") |
| delete(attrs, "source") |
| delete(attrs, "target") |
| if len(attrs) != 0 { |
| e.Attributes = attrs |
| } |
| return nil |
| } |