Skip to content

Commit b744b8e

Browse files
feat: ✨ Support complex JsonCols
1 parent 6a096bc commit b744b8e

2 files changed

Lines changed: 28 additions & 0 deletions

File tree

JsonApiToolkit.Tests/Mapping/JsonColumnMappingTests.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ public class EntityWithJsonColumns
1515
public ICollection<ExploitationReport> ExploitationReports { get; set; } =
1616
new List<ExploitationReport>();
1717

18+
// Single object with no ID property, simulating EF Core owned entity stored as JSON
19+
public ComplexJsonData ComplexData { get; set; } = new();
20+
1821
// This has an ID property, so should be a relationship
1922
public List<RelatedEntity> RelatedEntities { get; set; } = new();
2023
}
@@ -34,6 +37,14 @@ public class ExploitationReport
3437
// No Id property - this is owned entity stored as JSON
3538
}
3639

40+
public class ComplexJsonData
41+
{
42+
public string Category { get; set; } = string.Empty;
43+
public List<string> Tags { get; set; } = new();
44+
public Dictionary<string, object> Properties { get; set; } = new();
45+
// No Id property - this is owned entity stored as JSON
46+
}
47+
3748
public class RelatedEntity
3849
{
3950
public int Id { get; set; }
@@ -54,6 +65,7 @@ public void GetAttributeProperties_IncludesJsonColumns()
5465
Assert.Contains("Name", attributeNames);
5566
Assert.Contains("JsonDataList", attributeNames); // Should be included as attribute (no IDs)
5667
Assert.Contains("ExploitationReports", attributeNames); // Should be included as attribute (no IDs)
68+
Assert.Contains("ComplexData", attributeNames); // Should be included as attribute (single object with no ID)
5769
Assert.DoesNotContain("RelatedEntities", attributeNames); // Should NOT be attribute (has IDs)
5870
}
5971

@@ -70,6 +82,7 @@ public void GetRelationshipProperties_ExcludesJsonColumns()
7082
// Assert
7183
Assert.DoesNotContain("JsonDataList", relationshipNames); // Should NOT be relationship (no IDs)
7284
Assert.DoesNotContain("ExploitationReports", relationshipNames); // Should NOT be relationship (no IDs)
85+
Assert.DoesNotContain("ComplexData", relationshipNames); // Should NOT be relationship (single object with no ID)
7386
Assert.Contains("RelatedEntities", relationshipNames); // Should be relationship (has IDs)
7487
}
7588

@@ -100,6 +113,12 @@ public void ToResourceObject_MapsJsonColumnsAsAttributes()
100113
{
101114
new() { Description = "CVE-2024-1234", Severity = "High" },
102115
},
116+
ComplexData = new ComplexJsonData
117+
{
118+
Category = "Security",
119+
Tags = new List<string> { "vulnerability", "critical" },
120+
Properties = new Dictionary<string, object> { { "score", 9.5 } },
121+
},
103122
RelatedEntities = new List<RelatedEntity>
104123
{
105124
new() { Id = 10, Name = "Related 1" },
@@ -116,6 +135,7 @@ public void ToResourceObject_MapsJsonColumnsAsAttributes()
116135
// JSON columns should be in attributes
117136
Assert.True(resource.Attributes.ContainsKey("jsonDataList"));
118137
Assert.True(resource.Attributes.ContainsKey("exploitationReports"));
138+
Assert.True(resource.Attributes.ContainsKey("complexData"));
119139

120140
// Verify the JSON data is preserved
121141
var jsonDataList = resource.Attributes["jsonDataList"] as List<JsonData>;
@@ -127,6 +147,12 @@ public void ToResourceObject_MapsJsonColumnsAsAttributes()
127147
Assert.NotNull(exploitationReports);
128148
Assert.Single(exploitationReports);
129149

150+
var complexData = resource.Attributes["complexData"] as ComplexJsonData;
151+
Assert.NotNull(complexData);
152+
Assert.Equal("Security", complexData.Category);
153+
Assert.Equal(2, complexData.Tags.Count);
154+
Assert.True(complexData.Properties.ContainsKey("score"));
155+
130156
// RelatedEntities should NOT be in attributes (it's a relationship)
131157
Assert.False(resource.Attributes.ContainsKey("relatedEntities"));
132158
}

JsonApiToolkit/Mapping/EntityMapper.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ public static List<PropertyInfo> GetAttributeProperties(Type type)
119119
/// </list>
120120
/// <para>Excludes common value types like string, DateTime, and Guid.</para>
121121
/// <para>Collections of entities without ID properties (e.g., EF Core owned entities stored as JSON) are excluded and treated as attributes instead.</para>
122+
/// <para>Single complex objects without ID properties (e.g., EF Core owned entities stored as JSON) are excluded and treated as attributes instead.</para>
122123
/// </remarks>
123124
public static List<PropertyInfo> GetRelationshipProperties(Type type)
124125
{
@@ -145,6 +146,7 @@ public static List<PropertyInfo> GetRelationshipProperties(Type type)
145146
&& p.PropertyType != typeof(Guid)
146147
&& p.PropertyType != typeof(Guid?)
147148
&& !typeof(IEnumerable).IsAssignableFrom(p.PropertyType) // Exclude collections from complex object relationships
149+
&& HasIdProperty(p.PropertyType) // Only include single objects that have ID properties as relationships
148150
)
149151
)
150152
)

0 commit comments

Comments
 (0)