2017-09-16 16:02:26 +00:00
|
|
|
package jsonld
|
|
|
|
|
2017-10-01 15:09:04 +00:00
|
|
|
import (
|
|
|
|
"encoding/json"
|
2018-06-07 13:32:14 +00:00
|
|
|
"fmt"
|
|
|
|
"strings"
|
2017-10-02 09:53:09 +00:00
|
|
|
|
2018-07-06 10:48:04 +00:00
|
|
|
ap "github.com/mariusor/activitypub.go/activitypub"
|
2017-10-01 15:09:04 +00:00
|
|
|
)
|
2017-09-16 16:02:26 +00:00
|
|
|
|
2018-07-06 20:33:47 +00:00
|
|
|
var Ctx *Context
|
|
|
|
|
2018-03-25 18:54:51 +00:00
|
|
|
// Ref basic type
|
2017-09-16 16:02:26 +00:00
|
|
|
type Ref string
|
2017-10-01 15:09:04 +00:00
|
|
|
|
2018-03-25 18:54:51 +00:00
|
|
|
// Context is the basic JSON-LD element. It is used to map terms to IRIs.
|
|
|
|
// Terms are case sensitive and any valid string that is not a reserved JSON-LD
|
|
|
|
// keyword can be used as a term.
|
2017-09-16 16:02:26 +00:00
|
|
|
type Context struct {
|
2018-06-07 13:32:14 +00:00
|
|
|
URL Ref `jsonld:"@url"`
|
|
|
|
Language ap.LangRef `jsonld:"@language,omitempty,collapsible"`
|
2017-09-16 16:02:26 +00:00
|
|
|
}
|
|
|
|
|
2018-03-27 14:16:07 +00:00
|
|
|
// Collapsible is an interface used by the JSON-LD marshaller to collapse a struct to one single value
|
2018-03-26 21:12:04 +00:00
|
|
|
type Collapsible interface {
|
|
|
|
Collapse() []byte
|
|
|
|
}
|
|
|
|
|
2018-03-25 18:54:51 +00:00
|
|
|
// Ref returns a new Ref object based on Context URL
|
2017-09-30 21:36:05 +00:00
|
|
|
func (c *Context) Ref() Ref {
|
|
|
|
return Ref(c.URL)
|
2017-09-16 16:02:26 +00:00
|
|
|
}
|
2017-10-02 14:19:23 +00:00
|
|
|
|
2018-03-27 14:16:07 +00:00
|
|
|
// Collapse returns the plain text collapsed value of the current Context object
|
2018-03-26 21:12:04 +00:00
|
|
|
func (c *Context) Collapse() []byte {
|
|
|
|
return []byte(c.URL)
|
|
|
|
}
|
|
|
|
|
2018-03-25 18:54:51 +00:00
|
|
|
// MarshalText basic stringify function
|
2017-09-30 21:36:05 +00:00
|
|
|
func (r *Ref) MarshalText() ([]byte, error) {
|
|
|
|
return []byte(*r), nil
|
2017-09-16 16:02:26 +00:00
|
|
|
}
|
2017-10-02 15:24:26 +00:00
|
|
|
|
2018-03-25 18:54:51 +00:00
|
|
|
// MarshalJSON returns the JSON document represented by the current Context
|
2017-09-30 21:36:05 +00:00
|
|
|
func (c *Context) MarshalJSON() ([]byte, error) {
|
2018-03-25 17:35:10 +00:00
|
|
|
a := reflectToJSONValue(c)
|
2017-10-02 15:24:26 +00:00
|
|
|
if a.isScalar {
|
|
|
|
return json.Marshal(a.scalar)
|
|
|
|
}
|
2018-03-25 18:54:51 +00:00
|
|
|
return json.Marshal(a.object)
|
2017-09-16 16:02:26 +00:00
|
|
|
}
|
2018-06-07 13:32:14 +00:00
|
|
|
|
|
|
|
// UnmarshalJSON tries to load the Context from the incoming json value
|
|
|
|
func (c *Context) UnmarshalJSON(data []byte) error {
|
|
|
|
if data[0] == '"' {
|
|
|
|
// a quoted string - loading it to c.URL
|
|
|
|
if data[len(data)-1] != '"' {
|
|
|
|
return fmt.Errorf("invalid string value when unmarshalling Context value")
|
|
|
|
}
|
|
|
|
c.URL = Ref(data[1 : len(data)-1])
|
|
|
|
}
|
|
|
|
if data[0] == '{' {
|
|
|
|
// an object - trying to load it to the struct
|
|
|
|
if data[len(data)-1] != '}' {
|
|
|
|
return fmt.Errorf("invalid object value when unmarshalling Context value")
|
|
|
|
}
|
|
|
|
|
|
|
|
var s scanner
|
|
|
|
s.reset()
|
|
|
|
var d decodeState
|
|
|
|
d.scan = s
|
|
|
|
d.init(data)
|
|
|
|
|
|
|
|
d.scan.reset()
|
|
|
|
|
|
|
|
t := d.valueInterface()
|
|
|
|
|
|
|
|
for key, value := range t.(map[string]interface{}) {
|
|
|
|
switch strings.ToLower(key) {
|
|
|
|
case "@url":
|
|
|
|
fallthrough
|
|
|
|
case "url":
|
|
|
|
c.URL = Ref(value.(string))
|
|
|
|
case "@language":
|
|
|
|
fallthrough
|
|
|
|
case "language":
|
|
|
|
c.Language = ap.LangRef(value.(string))
|
|
|
|
default:
|
|
|
|
return fmt.Errorf("unkown Context field %q", key)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|