Added actor Json marshal

This commit is contained in:
Marius Orcsik 2019-12-19 13:34:04 +01:00
parent cf3741d6bb
commit c4d6f93c22
No known key found for this signature in database
GPG key ID: 889CE8E4FB2D877A
3 changed files with 160 additions and 10 deletions

135
actor.go
View file

@ -1,6 +1,7 @@
package activitypub
import (
"bytes"
"errors"
"github.com/buger/jsonparser"
"time"
@ -209,6 +210,36 @@ func (p *PublicKey) UnmarshalJSON(data []byte) error {
}
return nil
}
func (p PublicKey) MarshalJSON() ([]byte, error) {
b := bytes.Buffer{}
writeComma := func() { b.WriteString(",") }
writeCommaIfNotEmpty := func(notEmpty bool) {
if notEmpty {
writeComma()
}
}
notEmpty := true
b.Write([]byte{'{'})
if v, err := p.ID.MarshalJSON(); err == nil && len(v) > 0 {
notEmpty = !writeProp(&b, "id", v)
}
if p.Owner != nil {
writeCommaIfNotEmpty(notEmpty)
notEmpty = writeIRIProp(&b, "owner", p.Owner) || notEmpty
}
if len(p.PublicKeyPem) > 0 {
writeCommaIfNotEmpty(notEmpty)
notEmpty = writeIRIProp(&b, "publicKeyPem", p.Owner) || notEmpty
}
if notEmpty {
b.Write([]byte{'}'})
return b.Bytes(), nil
}
return nil, nil
}
type (
// Application describes a software application.
Application = Actor
@ -364,6 +395,65 @@ func (a *Actor) UnmarshalJSON(data []byte) error {
return nil
}
func (a Actor) MarshalJSON() ([]byte, error) {
b := bytes.Buffer{}
notEmpty := false
b.Write([]byte{'{'})
OnObject(a, func(o *Object) error {
notEmpty = writeObject(&b, *o)
return nil
})
writeComma := func() { b.WriteString(",") }
writeCommaIfNotEmpty := func(notEmpty bool) {
if notEmpty {
writeComma()
}
}
if a.Inbox != nil {
writeCommaIfNotEmpty(notEmpty)
notEmpty = writeItemProp(&b, "inbox", a.Inbox) || notEmpty
}
if a.Outbox != nil {
writeCommaIfNotEmpty(notEmpty)
notEmpty = writeItemProp(&b, "outbox", a.Outbox) || notEmpty
}
if a.Following != nil {
writeCommaIfNotEmpty(notEmpty)
notEmpty = writeItemProp(&b, "following", a.Following) || notEmpty
}
if a.Followers != nil {
writeCommaIfNotEmpty(notEmpty)
notEmpty = writeItemProp(&b, "followers", a.Followers) || notEmpty
}
if a.Liked != nil {
writeCommaIfNotEmpty(notEmpty)
notEmpty = writeItemProp(&b, "liked", a.Liked) || notEmpty
}
if a.Endpoints != nil {
writeCommaIfNotEmpty(notEmpty)
if v, err := a.Endpoints.MarshalJSON(); err == nil && len(v) > 0 {
notEmpty = writeProp(&b, "endpoints", v) || notEmpty
}
}
if len(a.Streams) > 0 {
writeCommaIfNotEmpty(notEmpty)
writePropName(&b, "streams")
lNotEmpty := true
for _, ss := range a.Streams {
writeCommaIfNotEmpty(lNotEmpty)
lNotEmpty = writeItemCollection(&b, ss) || lNotEmpty
}
notEmpty = lNotEmpty || notEmpty
}
if notEmpty {
b.Write([]byte{'}'})
return b.Bytes(), nil
}
return nil, nil
}
// Endpoints a json object which maps additional (typically server/domain-wide)
// endpoints which may be useful either for this actor or someone referencing this actor.
// This mapping may be nested inside the actor document as the value or may be a link to
@ -402,6 +492,49 @@ func (e *Endpoints) UnmarshalJSON(data []byte) error {
return nil
}
// MarshalJSON
func (e Endpoints) MarshalJSON() ([]byte, error) {
b := bytes.Buffer{}
notEmpty := false
writeComma := func() { b.WriteString(",") }
writeCommaIfNotEmpty := func(notEmpty bool) {
if notEmpty {
writeComma()
}
}
b.Write([]byte{'{'})
if e.OauthAuthorizationEndpoint != nil {
writeCommaIfNotEmpty(notEmpty)
notEmpty = writeItemProp(&b, "oauthAuthorizationEndpoint", e.OauthAuthorizationEndpoint) || notEmpty
}
if e.OauthTokenEndpoint != nil {
writeCommaIfNotEmpty(notEmpty)
notEmpty = writeItemProp(&b, "oauthTokenEndpoint", e.OauthTokenEndpoint) || notEmpty
}
if e.ProvideClientKey != nil {
writeCommaIfNotEmpty(notEmpty)
notEmpty = writeItemProp(&b, "provideClientKey", e.ProvideClientKey) || notEmpty
}
if e.SignClientKey != nil {
writeCommaIfNotEmpty(notEmpty)
notEmpty = writeItemProp(&b, "signClientKey", e.SignClientKey) || notEmpty
}
if e.SharedInbox != nil {
writeCommaIfNotEmpty(notEmpty)
notEmpty = writeItemProp(&b, "sharedInbox", e.SharedInbox) || notEmpty
}
if e.UploadMedia != nil {
writeCommaIfNotEmpty(notEmpty)
notEmpty = writeItemProp(&b, "uploadMedia", e.UploadMedia) || notEmpty
}
if notEmpty {
b.Write([]byte{'}'})
return b.Bytes(), nil
}
return nil, nil
}
// ToActor
func ToActor(it Item) (*Actor, error) {
switch i := it.(type) {
@ -410,6 +543,8 @@ func ToActor(it Item) (*Actor, error) {
case Actor:
return &i, nil
case *Object:
// TODO(marius): this is unsafe as Actor has a different memory layout than Actor
// Everything should be fine as long as you don't try to read the Actor specific collections
return (*Actor)(unsafe.Pointer(i)), nil
case Object:
return (*Actor)(unsafe.Pointer(&i)), nil

View file

@ -46,6 +46,9 @@ func writeNaturalLanguageProp(b *bytes.Buffer, n string, nl NaturalLanguageValue
func writeBoolProp(b *bytes.Buffer, n string, t bool) (notEmpty bool) {
return writeProp(b, n, []byte(fmt.Sprintf("%t", t)))
}
func writeIntProp(b *bytes.Buffer, n string, d int) (notEmpty bool) {
return writeProp(b, n, []byte(fmt.Sprintf("%d", d)))
}
func writeTimeProp(b *bytes.Buffer, n string, t time.Time) (notEmpty bool) {
if v, err := t.MarshalJSON(); err == nil {
return writeProp(b, n, v)
@ -94,11 +97,20 @@ func writeItemProp(b *bytes.Buffer, n string, i Item) (notEmpty bool) {
return notEmpty
}
func writeItemCollectionProp(b *bytes.Buffer, n string, col ItemCollection) (notEmpty bool) {
func writeString(b *bytes.Buffer, s string) (notEmpty bool) {
if len(s) == 0 {
return false
}
b.Write([]byte{'"'})
b.WriteString(s)
b.Write([]byte{'"'})
return true
}
func writeItemCollection(b *bytes.Buffer, col ItemCollection) (notEmpty bool) {
if len(col) == 0 {
return notEmpty
}
writePropName(b, n)
writeComma := func() { b.WriteString(",") }
writeCommaIfNotEmpty := func(notEmpty bool) {
if notEmpty {
@ -125,6 +137,13 @@ func writeItemCollectionProp(b *bytes.Buffer, n string, col ItemCollection) (not
b.Write([]byte{']'})
return notEmpty
}
func writeItemCollectionProp(b *bytes.Buffer, n string, col ItemCollection) (notEmpty bool) {
if len(col) == 0 {
return notEmpty
}
writePropName(b, n)
return writeItemCollection(b, col)
}
func writeObject(b *bytes.Buffer, o Object) (notEmpty bool) {
writeComma := func() { b.WriteString(",") }

View file

@ -112,9 +112,7 @@ func (a ActivityVocabularyType) MarshalJSON() ([]byte, error) {
return nil, nil
}
b := bytes.Buffer{}
b.Write([]byte{'"'})
b.WriteString(string(a))
b.Write([]byte{'"'})
writeString(&b, string(a))
return b.Bytes(), nil
}
@ -374,14 +372,12 @@ func (c *MimeType) UnmarshalJSON(data []byte) error {
}
// MarshalJSON
func (c MimeType) MarshalJSON() ([]byte, error) {
if len(c) == 0 {
func (m MimeType) MarshalJSON() ([]byte, error) {
if len(m) == 0 {
return nil, nil
}
b := bytes.Buffer{}
b.Write([]byte{'"'})
b.WriteString(string(c))
b.Write([]byte{'"'})
writeString(&b, string(m))
return b.Bytes(), nil
}