From 88cce1d2f9bf74bd98e389e79be4953d771faae6 Mon Sep 17 00:00:00 2001 From: Marius Orcsik Date: Sun, 15 Dec 2019 19:05:26 +0100 Subject: [PATCH] Adding some marshaler functions for Object related types --- object.go | 131 ++++++++++++++++++++++++++++++++++++++++++++++ object_id.go | 17 +++++- object_id_test.go | 8 +++ object_test.go | 20 +++++++ 4 files changed, 175 insertions(+), 1 deletion(-) diff --git a/object.go b/object.go index 7d1478b..efa42e4 100644 --- a/object.go +++ b/object.go @@ -1,6 +1,7 @@ package activitypub import ( + "bytes" "fmt" "github.com/buger/jsonparser" "strings" @@ -106,6 +107,17 @@ type ( MimeType string ) +func (a ActivityVocabularyType) MarshalJSON() ([]byte, error) { + if len(a) == 0 { + return nil, nil + } + b := bytes.Buffer{} + b.Write([]byte{'"'}) + b.WriteString(string(a)) + b.Write([]byte{'"'}) + return b.Bytes(), nil +} + // Object describes an ActivityPub object of any kind. // It serves as the base type for most of the other kinds of objects defined in the Activity // Vocabulary, including other Core types such as Activity, IntransitiveActivity, Collection and OrderedCollection. @@ -308,6 +320,92 @@ func (o *Object) UnmarshalJSON(data []byte) error { return nil } +func writeProp(b *bytes.Buffer, name string, val []byte) { + writePropName(b, name) + writeValue(b, val) +} +func writePropName(b *bytes.Buffer, s string) { + b.Write([]byte{'"'}) + b.WriteString(s) + b.Write([]byte{'"', ':'}) +} + +func writeValue(b *bytes.Buffer, s []byte) { + b.Write([]byte{'"'}) + b.Write(s) + b.Write([]byte{'"'}) +} + +func writeNaturalLanguageProp (b *bytes.Buffer, n string, nl NaturalLanguageValues) { + if v, err := nl.MarshalJSON(); err == nil { + if nl.Count() > 1 { + n += "Map" + } + writeProp(b, n, v) + } +} + +func writeItemProp (b *bytes.Buffer, n string, i Item) { + if i == nil { + b.WriteString("nil") + return + } + if i.IsObject() { + OnObject(i, func(o *Object) error { + v, err := o.MarshalJSON() + if err != nil { + return nil + } + writeProp(b, n, v) + return nil + }) + } else if i.IsCollection() { + OnCollection(i, func(c CollectionInterface) error { + writeItemCollectionProp(b, n, c.Collection()) + return nil + }) + } +} + +func writeItemCollectionProp (b *bytes.Buffer, n string, i ItemCollection) { +} + +// MarshalJSON +func (o Object) MarshalJSON() ([]byte, error) { + b := bytes.Buffer{} + writeComma := func () { b.WriteString(",") } + + if v, err := o.ID.MarshalJSON(); err == nil { + writeProp(&b, "id", v) + writeComma() + } + if v, err := o.Type.MarshalJSON(); err == nil { + writeProp(&b, "type", v) + writeComma() + } + if v, err := o.MediaType.MarshalJSON(); err == nil { + writeProp(&b, "mediaType", v) + writeComma() + } + if len(o.Name) > 0 { + writeNaturalLanguageProp(&b, "name", o.Name) + writeComma() + } + if len(o.Summary) > 0 { + writeNaturalLanguageProp(&b, "summary", o.Summary) + writeComma() + } + if len(o.Content) > 0 { + writeNaturalLanguageProp(&b, "content", o.Content) + writeComma() + } + + if v, err := o.Source.MarshalJSON(); err == nil { + writeProp(&b, "source", v) + } + return b.Bytes(), nil +} + // Recipients performs recipient de-duplication on the Object's To, Bto, CC and BCC properties func (o *Object) Recipients() ItemCollection { var aud ItemCollection @@ -346,6 +444,18 @@ func (c *MimeType) UnmarshalJSON(data []byte) error { return nil } +// MarshalJSON +func (c MimeType) MarshalJSON() ([]byte, error) { + if len(c) == 0 { + return nil, nil + } + b := bytes.Buffer{} + b.Write([]byte{'"'}) + b.WriteString(string(c)) + b.Write([]byte{'"'}) + return b.Bytes(), nil +} + // ToObject returns an Object pointer to the data in the current Item // It relies on the fact that all the types in this package have a data layout compatible with Object. func ToObject(it Item) (*Object, error) { @@ -464,3 +574,24 @@ func (s *Source) UnmarshalJSON(data []byte) error { *s = GetAPSource(data) return nil } + +// MarshalJSON +func (s Source) MarshalJSON() ([]byte, error) { + b := bytes.Buffer{} + b.Write([]byte{'{'}) + if len(s.MediaType) > 0 { + if v, err := s.MediaType.MarshalJSON(); err == nil { + writePropName(&b, "mediaType") + b.Write(v) + b.Write([]byte{','}) + } + } + if len(s.Content) > 0 { + if v, err := s.Content.MarshalJSON(); err == nil { + b.Write([]byte(`"content":`)) + b.Write(v) + } + } + b.Write([]byte{'}'}) + return b.Bytes(), nil +} diff --git a/object_id.go b/object_id.go index 26588a7..bd97ce8 100644 --- a/object_id.go +++ b/object_id.go @@ -1,6 +1,9 @@ package activitypub -import "strings" +import ( + "bytes" + "strings" +) // ID designates an unique global identifier. // All Objects in [ActivityStreams] should have unique global identifiers. @@ -22,6 +25,18 @@ func (i *ID) UnmarshalJSON(data []byte) error { return nil } +// MarshalJSON +func (i ID) MarshalJSON() ([]byte, error) { + if len(i) == 0 { + return nil, nil + } + b := bytes.Buffer{} + b.Write([]byte{'"'}) + b.WriteString(string(i)) + b.Write([]byte{'"'}) + return b.Bytes(), nil +} + func (i *ID) IsValid() bool { return i != nil && len(*i) > 0 } diff --git a/object_id_test.go b/object_id_test.go index a2001dd..45bc35d 100644 --- a/object_id_test.go +++ b/object_id_test.go @@ -11,3 +11,11 @@ func TestID_UnmarshalJSON(t *testing.T) { t.Errorf("Unmarshaled object %T should be an empty string, received %q", o, o) } } + +func TestID_IsValid(t *testing.T) { + t.Skip("TODO") +} + +func TestID_MarshalJSON(t *testing.T) { + t.Skip("TODO") +} diff --git a/object_test.go b/object_test.go index a0cb234..1dff148 100644 --- a/object_test.go +++ b/object_test.go @@ -488,3 +488,23 @@ func TestGetAPSource(t *testing.T) { t.Errorf("Content didn't match test value. Received %q, expecting %q", a.MediaType, "text/plain") } } + +func TestObject_Clean(t *testing.T) { + t.Skip("TODO") +} + +func TestObject_IsCollection(t *testing.T) { + t.Skip("TODO") +} + +func TestObject_MarshalJSON(t *testing.T) { + t.Skip("TODO") +} + +func TestSource_MarshalJSON(t *testing.T) { + t.Skip("TODO") +} + +func TestActivityVocabularyType_MarshalJSON(t *testing.T) { + t.Skip("TODO") +}