Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion pkg/processor/deserializer/json_deserializer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ package deserializer

import (
"encoding/json"
"fmt"
"os"
"sync"

"github.com/johnfercher/maroto/v2/pkg/processor/core"
"github.com/johnfercher/maroto/v2/pkg/processor/loader"
Expand All @@ -21,5 +24,48 @@ func NewJSONDeserializer() *jsonDeserializer {
func (j *jsonDeserializer) Deserialize(documentJSON string) (map[string]interface{}, error) {
var document map[string]interface{}
err := json.Unmarshal([]byte(documentJSON), &document)
return document, err
if err != nil {
return nil, err
}

resources, ok := document["Resources"].([]interface{})
if !ok {
return document, nil
}

document["Resources"] = j.loadResources(resources)

return document, nil
}

// loadResources method is responsible for loading each resource into
// memory via go routines
// `resources` should be type []map[string]interface{} with key "path"
// returns []map[string]interface{} with key "data" and the associated bytes of the file
func (j *jsonDeserializer) loadResources(resources []interface{}) []interface{} {
wg := sync.WaitGroup{}
for i, res := range resources {
resource, ok := res.(map[string]interface{})
if !ok {
continue
}
path, ok := resource["path"].(string)
if !ok {
continue
}

wg.Add(1)
go func(i int) {
defer wg.Done()
data, err := j.loader.Load(path)
if err != nil {
// TODO handle errors && io gracefully
fmt.Fprintln(os.Stderr, err.Error())
}
resource["data"] = data
resources[i] = resource
}(i)
}
wg.Wait()
return resources
}
69 changes: 69 additions & 0 deletions pkg/processor/deserializer/json_deserializer_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package deserializer_test

import (
"io"
"os"
"testing"

"github.com/johnfercher/maroto/v2/pkg/processor/deserializer"
"github.com/stretchr/testify/assert"
)

func TestDeserializer(t *testing.T) {
t.Run(
"when Resources array is not empty, it should return a document with the resources & data for each resource",
func(t *testing.T) {
input := `
{
"Resources": [
{
"name": "logo",
"path": "../../../docs/assets/images/logo.png"
},
{
"name": "font",
"path": "../../../docs/assets/fonts/arial-unicode-ms.ttf"
}
]
}`

got, err := deserializer.NewJSONDeserializer().Deserialize(input)
assert.NoError(t, err)
assert.NotNil(t, got)
assert.Contains(t, got, "Resources")

res, ok := got["Resources"].([]interface{})
assert.True(t, ok)
assert.Len(t, res, 2)

logoFile, err := os.Open("../../../docs/assets/images/logo.png")
if err != nil {
t.Fatal(err)
}
logoBytes, err := io.ReadAll(logoFile)
if err != nil {
t.Fatal(err)
}

fontFile, err := os.Open("../../../docs/assets/fonts/arial-unicode-ms.ttf")
if err != nil {
t.Fatal(err)
}
fontBytes, err := io.ReadAll(fontFile)
if err != nil {
t.Fatal(err)
}

assetBytes := [][]byte{logoBytes, fontBytes}

for i, obj := range res {
resource, ok := obj.(map[string]interface{})
assert.True(t, ok)
assert.Contains(t, resource, "data")
assert.IsType(t, resource["data"], []byte{})
assert.NotNil(t, resource["data"])
assert.Equal(t, assetBytes[i], resource["data"])
}
},
)
}