Skip to content

Commit

Permalink
Fix to dotnet#32939 - Accidentally using field instead of property fo…
Browse files Browse the repository at this point in the history
…r JSON metadata produce hard to understand exception (dotnet#32966)

When processing shaper for JSON streaming we didn't protect against the case where there are no properties on JSON entity that should be populated as part of the loop.
Fix check the count of properties we found before we start generating Switch-Case statement for PropertyName.

Fixes dotnet#32939
  • Loading branch information
maumar authored and roji committed Feb 9, 2024
1 parent 78a70b2 commit afd879d
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1822,32 +1822,43 @@ void ProcessFixup(IDictionary<string, LambdaExpression> fixupMap)
Empty()));
}

var switchCases = new List<SwitchCase>();
var testsCount = testExpressions.Count;
var testExpression = IfThen(
testExpressions[testsCount - 1],
readExpressions[testsCount - 1]);

for (var i = testsCount - 2; i >= 0; i--)
// generate PropertyName switch-case code
if (testsCount > 0)
{
testExpression = IfThenElse(
testExpressions[i],
readExpressions[i],
testExpression);
var testExpression = IfThen(
testExpressions[testsCount - 1],
readExpressions[testsCount - 1]);

for (var i = testsCount - 2; i >= 0; i--)
{
testExpression = IfThenElse(
testExpressions[i],
readExpressions[i],
testExpression);
}

switchCases.Add(
SwitchCase(
testExpression,
Constant(JsonTokenType.PropertyName)));
}

switchCases.Add(
SwitchCase(
Break(breakLabel),
Constant(JsonTokenType.EndObject)));

var loopBody = Block(
Assign(tokenTypeVariable, Call(managerVariable, Utf8JsonReaderManagerMoveNextMethod)),
Switch(
tokenTypeVariable,
Block(
Call(managerVariable, Utf8JsonReaderManagerSkipMethod),
Default(typeof(void))),
SwitchCase(
testExpression,
Constant(JsonTokenType.PropertyName)),
SwitchCase(
Break(breakLabel),
Constant(JsonTokenType.EndObject))));
switchCases.ToArray()));

return (Loop(loopBody, breakLabel), propertyAssignmentMap);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,59 @@ public virtual async Task Missing_navigation_works_with_deduplication(bool async

#endregion

#region 32939

[ConditionalFact]
public virtual async Task Project_json_with_no_properties()
{
var contextFactory = await InitializeAsync<Context32939>(seed: Seed30028);
using var context = contextFactory.CreateContext();
context.Entities.ToList();
}

protected void Seed30028(Context32939 ctx)
{
var entity = new Context32939.Entity32939
{
Empty = new Context32939.JsonEmpty32939(),
FieldOnly = new Context32939.JsonFieldOnly32939()
};

ctx.Entities.Add(entity);
ctx.SaveChanges();
}

protected class Context32939(DbContextOptions options) : DbContext(options)
{
public DbSet<Entity32939> Entities { get; set; }

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Entity32939>().Property(x => x.Id).ValueGeneratedNever();
modelBuilder.Entity<Entity32939>().OwnsOne(x => x.Empty, b => b.ToJson());
modelBuilder.Entity<Entity32939>().OwnsOne(x => x.FieldOnly, b => b.ToJson());
}

public class Entity32939
{
public int Id { get; set; }
public JsonEmpty32939 Empty { get; set; }
public JsonFieldOnly32939 FieldOnly { get; set; }

}

public class JsonEmpty32939
{
}

public class JsonFieldOnly32939
{
public int Field;
}
}

#endregion

#region ArrayOfPrimitives

[ConditionalTheory]
Expand Down

0 comments on commit afd879d

Please sign in to comment.