Skip to content

fix: map metadata to objectmeta #292

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

Merged
merged 7 commits into from
Jul 31, 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
1 change: 1 addition & 0 deletions gateway/schema/exports_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package schema
import "k8s.io/apimachinery/pkg/runtime/schema"

var StringMapScalarForTest = stringMapScalar
var JSONStringScalarForTest = jsonStringScalar

func GetGatewayForTest(typeNameRegistry map[string]string) *Gateway {
return &Gateway{
Expand Down
38 changes: 38 additions & 0 deletions gateway/schema/scalars.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package schema

import (
"encoding/json"

"github.com/graphql-go/graphql"
"github.com/graphql-go/graphql/language/ast"
)
Expand Down Expand Up @@ -34,3 +36,39 @@ var stringMapScalar = graphql.NewScalar(graphql.ScalarConfig{
}
},
})

var jsonStringScalar = graphql.NewScalar(graphql.ScalarConfig{
Name: "JSONString",
Description: "A JSON-serialized string representation of any object.",
Serialize: func(value interface{}) interface{} {
// Convert the value to JSON string
jsonBytes, err := json.Marshal(value)
if err != nil {
// Fallback to empty JSON object if marshaling fails
return "{}"
}
return string(jsonBytes)
},
ParseValue: func(value interface{}) interface{} {
if str, ok := value.(string); ok {
var result interface{}
err := json.Unmarshal([]byte(str), &result)
if err != nil {
return nil // Invalid JSON
}
return result
}
return nil
},
ParseLiteral: func(valueAST ast.Value) interface{} {
if value, ok := valueAST.(*ast.StringValue); ok {
var result interface{}
err := json.Unmarshal([]byte(value.Value), &result)
if err != nil {
return nil // Invalid JSON
}
return result
}
return nil
},
})
49 changes: 49 additions & 0 deletions gateway/schema/scalars_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package schema_test

import (
"encoding/json"
"reflect"
"testing"

Expand Down Expand Up @@ -153,3 +154,51 @@ func TestGenerateTypeName(t *testing.T) {
})
}
}

func TestJSONStringScalar_ProperSerialization(t *testing.T) {
testObject := map[string]interface{}{
"name": "example-config",
"namespace": "default",
"labels": map[string]string{
"hello": "world",
},
"annotations": map[string]string{
"kcp.io/cluster": "root",
},
}

// Test the JSONString scalar serialization
result := schema.JSONStringScalarForTest.Serialize(testObject)

if result == nil {
t.Fatal("JSONStringScalar.Serialize returned nil")
}

resultStr, ok := result.(string)
if !ok {
t.Fatalf("JSONStringScalar.Serialize returned %T, expected string", result)
}

// Verify it's valid JSON
var parsed map[string]interface{}
err := json.Unmarshal([]byte(resultStr), &parsed)
if err != nil {
t.Fatalf("Result is not valid JSON: %s\nResult: %s", err, resultStr)
}

// Verify the content is preserved
if parsed["name"] != "example-config" {
t.Errorf("Name not preserved: got %v, want %v", parsed["name"], "example-config")
}

if parsed["namespace"] != "default" {
t.Errorf("Namespace not preserved: got %v, want %v", parsed["namespace"], "default")
}

// Verify it's NOT Go map format
if len(resultStr) > 10 && resultStr[:4] == "map[" {
t.Errorf("Result is in Go map format, not JSON: %s", resultStr)
}

t.Logf("Proper JSON output: %s", resultStr)
}
4 changes: 2 additions & 2 deletions gateway/schema/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,8 +453,8 @@ func (g *Gateway) handleObjectFieldSpecType(fieldSpec spec.Schema, typePrefix st
}
}

// It's an empty object
return graphql.String, graphql.String, nil
// It's an empty object, serialize as JSON string
return jsonStringScalar, jsonStringScalar, nil
}

func (g *Gateway) generateTypeName(typePrefix string, fieldPath []string) string {
Expand Down