Repository: jomei/notionapi
Pull request #94 (2022-06-23 11:03:51)

Fixed a bug that prevented the creation of a database with the Number property
close https://github.com/jomei/notionapi/issues/92

## problem

An error occurs when trying to create a database with the Number property.

The cause was that the JSON structure of the number property did not conform to the API specification ([API doc](https://developers.notion.com/reference/property-object#number-configuration)). The format property must be contained within the number property.

<table>
<thead><tr><th>NG(before)</th><th>OK(after)</th></tr></thead>
<tbody>
<tr><td>

```json
"properties": {
  "some number": {
    "type": "number",
    "format": "number"
  }
}
```

</td><td>

```json
"properties": {
  "some number": {
    "type": "number",
    "number": {
      "format": "number"
    }
  }
}
```

</td></tr>
</tbody></table>

> Number database property objects contain the following configuration within the number property:
https://developers.notion.com/reference/property-object#number-configuration

Sample code that can reproduce the error
```go
client := notionapi.NewClient(token)
req := &notionapi.DatabaseCreateRequest{
	Parent: notionapi.Parent{
		Type:   notionapi.ParentTypePageID,
		PageID: "c85c03a496a44d958a1d8e823b9ff4e6",
	},
	Title: []notionapi.RichText{
		{
			Type: notionapi.ObjectTypeText,
			Text: notionapi.Text{Content: "Sample"},
		},
	},
	Properties: notionapi.PropertyConfigs{
		"Title": notionapi.TitlePropertyConfig{
			Type: notionapi.PropertyConfigTypeTitle,
		},
		"Number": notionapi.NumberPropertyConfig{
			Type:   notionapi.PropertyConfigTypeNumber,
			Format: notionapi.FormatDollar,
		},
	},
}
db, err := client.Database.Create(context.Background(), req)
if err != nil {
	log.Println(err)
}
log.Println(db)
```

error log
```
2022/06/23 05:00:46 body failed validation. Fix one:
body.properties.Phone Number.number should be defined, instead was `undefined`.
body.properties.Phone Number.formula should be defined, instead was `undefined`.
body.properties.Phone Number.select should be defined, instead was `undefined`.
body.properties.Phone Number.multi_select should be defined, instead was `undefined`.
body.properties.Phone Number.status should be defined, instead was `undefined`.
body.properties.Phone Number.relation should be defined, instead was `undefined`.
body.properties.Phone Number.rollup should be defined, instead was `undefined`.
body.properties.Phone Number.title should be defined, instead was `undefined`.
body.properties.Phone Number.rich_text should be defined, instead was `undefined`.
body.properties.Phone Number.url should be defined, instead was `undefined`.
body.properties.Phone Number.people should be defined, instead was `undefined`.
body.properties.Phone Number.files should be defined, instead was `undefined`.
body.properties.Phone Number.email should be defined, instead was `undefined`.
body.properties.Phone Number.type should be `"phone_number"` or `undefined`, instead was `""`.
body.properties.Phone Number.date should be defined, instead was `undefined`.
body.properties.Phone Number.checkbox should be defined, instead was `undefined`.
body.properties.Phone Number.created_by should be defined, instead was `undefined`.
body.properties.Phone Number.created_time should be defined, instead was `undefined`.
body.properties.Phone Number.last_edited_by should be defined, instead was `undefined`.
body.properties.Phone Number.last_edited_time should be defined, instead was `undefined`.
```

## fix
To maintain backward compatibility, we left the format field as is. Instead, a custom marshalJSON() was added.

What do you think about keeping a backward compatibility system?


Patch:
diff --git a/property_config.go b/property_config.go
index c017117..fe4e66d 100644
--- a/property_config.go
+++ b/property_config.go
@@ -32,9 +32,11 @@ func (p RichTextPropertyConfig) GetType() PropertyConfigType {
 }
 
 type NumberPropertyConfig struct {
-	ID     ObjectID           `json:"id,omitempty"`
-	Type   PropertyConfigType `json:"type"`
-	Format FormatType         `json:"format"`
+	ID   ObjectID           `json:"id,omitempty"`
+	Type PropertyConfigType `json:"type"`
+	// Deprecated: use Number instead.
+	Format FormatType   `json:"format,omitempty"`
+	Number NumberFormat `json:"number"`
 }
 
 type FormatType string
@@ -43,6 +45,10 @@ func (ft FormatType) String() string {
 	return string(ft)
 }
 
+type NumberFormat struct {
+	Format FormatType `json:"format"`
+}
+
 func (p NumberPropertyConfig) GetType() PropertyConfigType {
 	return p.Type
 }


Test patch:
diff --git a/property_config_test.go b/property_config_test.go
new file mode 100644
index 0000000..92ff5e8
--- /dev/null
+++ b/property_config_test.go
@@ -0,0 +1,46 @@
+package notionapi
+
+import (
+	"encoding/json"
+	"reflect"
+	"testing"
+)
+
+func TestNumberPropertyConfig_MarshalJSON(t *testing.T) {
+	type fields struct {
+		Type   PropertyConfigType
+		Format FormatType
+	}
+	tests := []struct {
+		name    string
+		fields  fields
+		want    []byte
+		wantErr bool
+	}{
+		{
+			name: "returns correct json",
+			fields: fields{
+				Type:   PropertyConfigTypeNumber,
+				Format: FormatDollar,
+			},
+			want:    []byte(`{"type":"number","number":{"format":"dollar"}}`),
+			wantErr: false,
+		},
+	}
+	for _, tt := range tests {
+		t.Run(tt.name, func(t *testing.T) {
+			p := NumberPropertyConfig{
+				Type:   tt.fields.Type,
+				Number: NumberFormat{Format: tt.fields.Format},
+			}
+			got, err := json.Marshal(p)
+			if (err != nil) != tt.wantErr {
+				t.Errorf("MarshalJSON() error = %v, wantErr %v", err, tt.wantErr)
+				return
+			}
+			if !reflect.DeepEqual(got, tt.want) {
+				t.Errorf("MarshalJSON() got = %v, want %v", string(got), string(tt.want))
+			}
+		})
+	}
+}