Skip to content

Commit

Permalink
Merge pull request #116 from microsoft/feature/serialization-helpers
Browse files Browse the repository at this point in the history
feature/serialization helpers
  • Loading branch information
baywet committed Nov 2, 2023
2 parents c6b1cb2 + f3dfa5c commit e7cbf65
Show file tree
Hide file tree
Showing 8 changed files with 326 additions and 8 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Expand Up @@ -11,6 +11,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

## [1.4.0] - 2023-11-01

### Added

- Added serialization helpers. [microsoft/kiota#3406](https://github.com/microsoft/kiota/issues/3406)

## [1.3.1] - 2023-10-31

### Changed
Expand Down
6 changes: 5 additions & 1 deletion api_client_builder_test.go
Expand Up @@ -2,11 +2,12 @@ package abstractions

import (
"fmt"
"github.com/microsoft/kiota-abstractions-go/store"
"reflect"
"testing"
"time"

"github.com/microsoft/kiota-abstractions-go/store"

"github.com/microsoft/kiota-abstractions-go/internal"
serialization "github.com/microsoft/kiota-abstractions-go/serialization"
assert "github.com/stretchr/testify/assert"
Expand All @@ -22,6 +23,7 @@ func TestItCreatesClientConcurrently(t *testing.T) {
waitTime, _ := time.ParseDuration("100ms") // otherwise the routines might not be completed
time.Sleep(waitTime)
assert.Equal(t, 1, len(serialization.DefaultSerializationWriterFactoryInstance.ContentTypeAssociatedFactories))
serialization.DefaultSerializationWriterFactoryInstance.ContentTypeAssociatedFactories = make(map[string]serialization.SerializationWriterFactory)
}

func TestEnableBackingStoreForSerializationWriterFactory(t *testing.T) {
Expand All @@ -35,6 +37,7 @@ func TestEnableBackingStoreForSerializationWriterFactory(t *testing.T) {

EnableBackingStoreForSerializationWriterFactory(factory)
assert.IsType(t, &store.BackingStoreSerializationWriterProxyFactory{}, serializationFactoryRegistry.ContentTypeAssociatedFactories[StreamContentType])
serialization.DefaultSerializationWriterFactoryInstance.ContentTypeAssociatedFactories = make(map[string]serialization.SerializationWriterFactory)
}

func TestEnableBackingStoreForParseNodeFactory(t *testing.T) {
Expand All @@ -48,6 +51,7 @@ func TestEnableBackingStoreForParseNodeFactory(t *testing.T) {

EnableBackingStoreForParseNodeFactory(factory)
assert.IsType(t, &store.BackingStoreParseNodeFactory{}, parseNodeRegistry.ContentTypeAssociatedFactories[StreamContentType])
serialization.DefaultParseNodeFactoryInstance.ContentTypeAssociatedFactories = make(map[string]serialization.ParseNodeFactory)
}

// IsType asserts that the specified objects are of the same type.
Expand Down
47 changes: 41 additions & 6 deletions internal/mock_serializer.go
Expand Up @@ -8,7 +8,8 @@ import (
)

type MockSerializer struct {
CallsCounter map[string]int
CallsCounter map[string]int
SerializedValue string
}

func (m *MockSerializer) WriteNullValue(key string) error {
Expand Down Expand Up @@ -130,7 +131,10 @@ func (*MockSerializer) WriteCollectionOfTimeOnlyValues(key string, collection []
func (*MockSerializer) WriteCollectionOfUUIDValues(key string, collection []uuid.UUID) error {
return nil
}
func (*MockSerializer) GetSerializedContent() ([]byte, error) {
func (m *MockSerializer) GetSerializedContent() ([]byte, error) {
if m.SerializedValue != "" {
return []byte(m.SerializedValue), nil
}
return []byte("content"), nil
}
func (*MockSerializer) WriteAdditionalData(value map[string]interface{}) error {
Expand All @@ -145,6 +149,7 @@ func (*MockSerializer) Close() error {

type MockSerializerFactory struct {
serialization.SerializationWriter
SerializedValue string
}

func (*MockSerializerFactory) GetValidContentType() (string, error) {
Expand All @@ -153,17 +158,47 @@ func (*MockSerializerFactory) GetValidContentType() (string, error) {
func (m *MockSerializerFactory) GetSerializationWriter(contentType string) (serialization.SerializationWriter, error) {
if m.SerializationWriter == nil {
m.SerializationWriter = &MockSerializer{
CallsCounter: make(map[string]int),
CallsCounter: make(map[string]int),
SerializedValue: m.SerializedValue,
}
}
return m.SerializationWriter, nil
}

type MockParseNodeFactory struct {
serialization.ParseNodeFactoryRegistry
serialization.ParseNodeFactory
SerializedValue any
}

func NewMockParseNodeFactory() *MockParseNodeFactory {
registry := serialization.NewParseNodeFactoryRegistry()
return &MockParseNodeFactory{*registry}
return &MockParseNodeFactory{}
}
func (*MockParseNodeFactory) GetValidContentType() (string, error) {
return "application/json", nil
}

type MockParseNode struct {
serialization.ParseNode
SerializedValue any
}

func (m *MockParseNodeFactory) GetRootParseNode(contentType string, content []byte) (serialization.ParseNode, error) {
return &MockParseNode{
SerializedValue: m.SerializedValue,
}, nil
}

func (m *MockParseNode) GetObjectValue(ctor serialization.ParsableFactory) (serialization.Parsable, error) {
castValue, ok := m.SerializedValue.(serialization.Parsable)
if ok {
return castValue, nil
}
return ctor(m)
}
func (m *MockParseNode) GetCollectionOfObjectValues(ctor serialization.ParsableFactory) ([]serialization.Parsable, error) {
castValue, ok := m.SerializedValue.([]serialization.Parsable)
if ok {
return castValue, nil
}
return nil, nil
}
17 changes: 17 additions & 0 deletions internal/person.go
Expand Up @@ -3,6 +3,7 @@ package internal
import "github.com/microsoft/kiota-abstractions-go/serialization"

type Person struct {
id *string
displayName *string
callRecord *CallRecord
callRecords []*CallRecord
Expand Down Expand Up @@ -38,6 +39,15 @@ func (c *CallRecord) GetFieldDeserializers() map[string]func(serialization.Parse
func NewCallRecord() *CallRecord {
return &CallRecord{}
}
func CreatePersonFromDiscriminatorValue(parseNode serialization.ParseNode) (serialization.Parsable, error) {
return &Person{}, nil
}
func (c *Person) SetId(id *string) {
c.id = id
}
func (c *Person) GetId() *string {
return c.id
}
func (u *Person) SetDisplayName(name *string) {
u.displayName = name
}
Expand Down Expand Up @@ -85,3 +95,10 @@ func (u *Person) SetCardNumbers(numbers []int) {
func (u *Person) GetCardNumbers() []int {
return u.cardNumbers
}
func (c *Person) Serialize(writer serialization.SerializationWriter) error {
panic("implement me")
}

func (c *Person) GetFieldDeserializers() map[string]func(serialization.ParseNode) error {
panic("implement me")
}
143 changes: 143 additions & 0 deletions kiota_serializer_test.go
@@ -0,0 +1,143 @@
package abstractions

import (
"testing"

"github.com/microsoft/kiota-abstractions-go/internal"
"github.com/microsoft/kiota-abstractions-go/serialization"
assert "github.com/stretchr/testify/assert"
)

var jsonContentType = "application/json"

func TestItDefendsSerializationEmptyContentType(t *testing.T) {
result, err := serialization.Serialize("", nil)
assert.Nil(t, result)
assert.NotNil(t, err)
}

func TestItDefendsSerializationNilValue(t *testing.T) {
result, err := serialization.Serialize(jsonContentType, nil)
assert.Nil(t, result)
assert.NotNil(t, err)
}

func TestItDefendsCollectionSerializationEmptyContentType(t *testing.T) {
result, err := serialization.SerializeCollection("", nil)
assert.Nil(t, result)
assert.NotNil(t, err)
}

func TestItDefendsCollectionSerializationNilValue(t *testing.T) {
result, err := serialization.SerializeCollection(jsonContentType, nil)
assert.Nil(t, result)
assert.NotNil(t, err)
}

func TestItSerializesObject(t *testing.T) {
serializedValue := "{\"id\":\"123\"}"
metaFactory := func() serialization.SerializationWriterFactory {
return &internal.MockSerializerFactory{
SerializedValue: serializedValue,
}
}
RegisterDefaultSerializer(metaFactory)
person := internal.NewPerson()
id := "123"
person.SetId(&id)
result, err := serialization.Serialize(jsonContentType, person)
assert.Nil(t, err)
assert.NotNil(t, result)
assert.Equal(t, serializedValue, string(result))
serialization.DefaultSerializationWriterFactoryInstance.ContentTypeAssociatedFactories = make(map[string]serialization.SerializationWriterFactory)
}

func TestItSerializesACollectionOfObjects(t *testing.T) {
serializedValue := "[{\"id\":\"123\"}]"
metaFactory := func() serialization.SerializationWriterFactory {
return &internal.MockSerializerFactory{
SerializedValue: serializedValue,
}
}
RegisterDefaultSerializer(metaFactory)
person := internal.NewPerson()
id := "123"
person.SetId(&id)
result, err := serialization.SerializeCollection(jsonContentType, []serialization.Parsable{person})
assert.Nil(t, err)
assert.NotNil(t, result)
assert.Equal(t, serializedValue, string(result))
serialization.DefaultSerializationWriterFactoryInstance.ContentTypeAssociatedFactories = make(map[string]serialization.SerializationWriterFactory)
}

func TestItDefendsDeserializationEmptyContentType(t *testing.T) {
result, err := serialization.Deserialize("", nil, nil)
assert.Nil(t, result)
assert.NotNil(t, err)
}
func TestItDefendsDeserializationNilContent(t *testing.T) {
result, err := serialization.Deserialize(jsonContentType, nil, nil)
assert.Nil(t, result)
assert.NotNil(t, err)
}
func TestItDefendsDeserializationNilFactory(t *testing.T) {
result, err := serialization.Deserialize(jsonContentType, make([]byte, 0), nil)
assert.Nil(t, result)
assert.NotNil(t, err)
}

func TestItDefendsCollectionDeserializationEmptyContentType(t *testing.T) {
result, err := serialization.DeserializeCollection("", nil, nil)
assert.Nil(t, result)
assert.NotNil(t, err)
}
func TestItDefendsCollectionDeserializationNilContent(t *testing.T) {
result, err := serialization.DeserializeCollection(jsonContentType, nil, nil)
assert.Nil(t, result)
assert.NotNil(t, err)
}
func TestItDefendsCollectionDeserializationNilFactory(t *testing.T) {
result, err := serialization.DeserializeCollection(jsonContentType, make([]byte, 0), nil)
assert.Nil(t, result)
assert.NotNil(t, err)
}

func TestItDeserializesAnObject(t *testing.T) {
person := internal.NewPerson()
id := "123"
person.SetId(&id)
metaFactory := func() serialization.ParseNodeFactory {
return &internal.MockParseNodeFactory{
SerializedValue: person,
}
}
RegisterDefaultDeserializer(metaFactory)

result, err := serialization.Deserialize(jsonContentType, []byte("{\"id\": \"123\"}"), internal.CreatePersonFromDiscriminatorValue)
assert.Nil(t, err)
assert.NotNil(t, result)
resultAsPerson, ok := result.(*internal.Person)
assert.True(t, ok)
assert.Equal(t, id, *resultAsPerson.GetId())
serialization.DefaultParseNodeFactoryInstance.ContentTypeAssociatedFactories = make(map[string]serialization.ParseNodeFactory)
}

func TestItDeserializesAnObjectCollection(t *testing.T) {
person := internal.NewPerson()
id := "123"
person.SetId(&id)
metaFactory := func() serialization.ParseNodeFactory {
return &internal.MockParseNodeFactory{
SerializedValue: []serialization.Parsable{person},
}
}
RegisterDefaultDeserializer(metaFactory)

result, err := serialization.DeserializeCollection(jsonContentType, []byte("[{\"id\": \"123\"}]"), internal.CreatePersonFromDiscriminatorValue)
assert.Nil(t, err)
assert.NotNil(t, result)
resultAsPerson, ok := result[0].(*internal.Person)
assert.True(t, ok)
assert.Equal(t, id, *resultAsPerson.GetId())
serialization.DefaultParseNodeFactoryInstance.ContentTypeAssociatedFactories = make(map[string]serialization.ParseNodeFactory)
}
23 changes: 23 additions & 0 deletions serialization/kiota_json_serializer.go
@@ -0,0 +1,23 @@
package serialization

var jsonContentType = "application/json"

// SerializeToJson serializes the given model to JSON
func SerializeToJson(model Parsable) ([]byte, error) {
return Serialize(jsonContentType, model)
}

// SerializeCollectionToJson serializes the given models to JSON
func SerializeCollectionToJson(models []Parsable) ([]byte, error) {
return SerializeCollection(jsonContentType, models)
}

// DeserializeFromJson deserializes the given JSON to a model
func DeserializeFromJson(content []byte, parsableFactory ParsableFactory) (Parsable, error) {
return Deserialize(jsonContentType, content, parsableFactory)
}

// DeserializeCollectionFromJson deserializes the given JSON to a collection of models
func DeserializeCollectionFromJson(content []byte, parsableFactory ParsableFactory) ([]Parsable, error) {
return DeserializeCollection(jsonContentType, content, parsableFactory)
}

0 comments on commit e7cbf65

Please sign in to comment.