Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(server): use string as default field type in item import #1428

Merged
merged 2 commits into from
Mar 4, 2025
Merged
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
10 changes: 6 additions & 4 deletions server/e2e/integration_item_import_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,14 +208,15 @@ func TestIntegrationModelImportJSONWithGeoJsonInput(t *testing.T) {
func TestIntegrationModelImportJSONWithJsonInput1(t *testing.T) {
e := StartServer(t, &app.Config{}, true, baseSeederUser)

// region strategy="insert" and mutateSchema=false
pId, _ := createProject(e, wId.String(), "test", "test", "test-1")
mId, _ := createModel(e, pId, "test", "test", "test-1")
createFieldOfEachType(t, e, mId)

// 3 items with predefined fields
jsonContent := `[{"text": "test1", "bool": true, "number": 1.1},{"text": "test2", "bool": false, "number": 2},{"text": "test3", "bool": null, "number": null}]`
jsonContent := `[{"text": "test1", "bool": true, "number": 1.1, "text2": null},{"text": "test2", "bool": false, "number": 2},{"text": "test3", "bool": null, "number": null}]`
aId := uploadAsset(e, pId, "./test1.json", jsonContent).Object().Value("id").String().Raw()

// region strategy="insert" and mutateSchema=false
res := IntegrationModelImportJSON(e, mId, aId, "json", "insert", false, nil)
res.Object().IsEqual(map[string]any{
"modelId": mId,
Expand Down Expand Up @@ -265,9 +266,10 @@ func TestIntegrationModelImportJSONWithJsonInput1(t *testing.T) {
"updatedCount": 0,
"ignoredCount": 0,
})
res.Object().Value("newFields").Array().Length().IsEqual(3)
res.Object().Value("newFields").Array().Length().IsEqual(4)
// insure the same order of fields
res.Path("$.newFields[:].type").Array().IsEqual([]string{"text", "bool", "number"})
res.Path("$.newFields[:].key").Array().IsEqual([]string{"text", "bool", "number", "text2"})
res.Path("$.newFields[:].type").Array().IsEqual([]string{"text", "bool", "number", "text"})

obj = e.GET("/api/models/{modelId}/items", mId).
// WithHeader("authorization", "Bearer "+secret).
Expand Down
43 changes: 22 additions & 21 deletions server/internal/usecase/interactor/item_import.go
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ func guessSchemaFields(sp schema.Package, orderedMap *orderedmap.OrderedMap, isG
}
for _, k := range orderedMap.Keys() {
v, _ := orderedMap.Get(k)
if v == nil || k == "id" {
if k == "id" {
continue
}
Comment on lines +476 to 478
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix for null field handling in schema detection.

This change allows the guessSchemaFields function to process keys with nil values by removing the condition that skipped them. Now it only skips the "id" field and processes all other fields, including those with null values.

This fix ensures that JSON fields with null values will be properly detected and included in the schema, providing better compatibility with diverse data sources.


Expand Down Expand Up @@ -505,26 +505,27 @@ func guessSchemaFields(sp schema.Package, orderedMap *orderedmap.OrderedMap, isG

func fieldFrom(k string, v any, sp schema.Package) interfaces.CreateFieldParam {
t := value.TypeText
switch reflect.TypeOf(v).Kind() {
case reflect.Bool:
t = value.TypeBool
case reflect.Int:
case reflect.Int8:
case reflect.Int16:
case reflect.Int32:
case reflect.Int64:
case reflect.Uint:
case reflect.Uint8:
case reflect.Uint16:
case reflect.Uint32:
case reflect.Uint64:
case reflect.Float32:
case reflect.Float64:
t = value.TypeNumber
case reflect.String:
t = value.TypeText
default:

if v != nil {
switch reflect.TypeOf(v).Kind() {
case reflect.Bool:
t = value.TypeBool
case reflect.Int:
case reflect.Int8:
case reflect.Int16:
case reflect.Int32:
case reflect.Int64:
case reflect.Uint:
case reflect.Uint8:
case reflect.Uint16:
case reflect.Uint32:
case reflect.Uint64:
case reflect.Float32:
case reflect.Float64:
t = value.TypeNumber
case reflect.String:
t = value.TypeText
default:
}
}
return interfaces.CreateFieldParam{
ModelID: nil,
Expand Down