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

How to deal with dictionary items in entity for .ToJson functionality #31257

Closed
MacMcDell opened this issue Jul 13, 2023 · 7 comments
Closed

Comments

@MacMcDell
Copy link

MacMcDell commented Jul 13, 2023

How to deal with dictionary items in Json?

I am banging my head against a wall trying to get a dictionary within a poco to behave nicely when storing the data as Json. I am using EFCore 7.08. Why does this seem so difficult to get done? What am I missing to understand here?. MatchSuccess Has/Owns? a property that is a collection.
All I want to get stored is something that looks like reasonable json
example of what I want in db:

[{ "Foo": "222",    "Bar": "269506",    "Meta": {      "SpaceId": "123728"  }  }] //The Meta prop is the issue.

vs what I get in db:

[{"Meta":"{\u0022SpaceId\u0022:\u0022123728\u0022}","Foo":"222","Bar":"269506"}]

As you cannot see... I can easily parse this back out.

setup

I have a very simple POCO like this:

public class MatchSuccess
{
    public MatchSuccess()
    {
        Meta = new Dictionary<string, string>();
    }
   
    public string Foo{ get; set; }
    public string Bar{ get; set; }
    public Dictionary<string, string> Meta { get; set; } // <<<<This is a mess
}

It gets used here:

public class DtoObject: 
{
    public int Id { get; set; }
    public List<MatchSuccess> MatchSuccesses { get; set; } = new List<MatchSuccess>(); //<<<It is a list
    public List<MatchFailure> MatchFailures { get; set; } = new List<MatchFailure>();
}

my builder looks like this:

 modelBuilder.Entity<DtoObject>(dto=>
        {
            dto.OwnsMany(e=> e.MatchSuccesses, matchSuccessBuilder =>
            {
                matchSuccessBuilder.ToJson();
                //matchSuccessBuilder.OwnsOne(matchSuccess => matchSuccess.Meta, metaBuilder => { metaBuilder.ToJson();}); 
               // creates :   @p1='[{"Foo":"236129","Bar":"888","Meta":{}}]' (Nullable = false) 
               
                 matchSuccessBuilder.HasOne(matchSuccess => matchSuccess.Meta);
                ^^^ Throws exception
                
               // matchSuccessBuilder.OwnsOne<Dictionary<string,string>>(c => c.Meta, b =>  { b.ToJson(); });
               // creates:  @p1='[{"Foo":"236129","Bar":"888","Meta":{}}]'
               
                 // matchSuccessBuilder.Property(p => p.Meta)
                //     .HasConversion(
                //         v => JsonSerializer.Serialize(v, options),
                //         v => JsonSerializer.Deserialize<Dictionary<string, string>>(v, options));
               // creates:  @p1='[{"Meta":"{\u0022SpaceId\u0022:\u0022236129\u0022}","Foo":"236129","Bar":"888"}]' 

            });
            dto.OwnsMany(e => e.MatchFailures, b =>  {  b.ToJson();   });

my serializer options are:

 var options = new JsonSerializerOptions()
        {
            PropertyNameCaseInsensitive = true,
            PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
            WriteIndented = false,
           Encoder  = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
        };

This thing is slowly killing me.

Include provider and version information

EF Core version: 7.08
Database provider: (e.g. Microsoft.EntityFrameworkCore.SqlServer)
Target framework: .NET 6.0
Operating system: IDE: Rider

@ajcvickers
Copy link
Contributor

Note for triage: likely covered by #31257, but not covered by #29427.

@MacMcDell
Copy link
Author

@ajcvickers i read the other post regarding primitives and see there was some commits to ef8. Is using the property / conversion the only supported way to do what I need in ef7? Does ef8 support this now to have just a nice array of string,string?

@roji
Copy link
Member

roji commented Jul 16, 2023

@MacMcDell EF8 will bring 1st-class support for primitive lists/arrays, but not for dictionaries. In both EF7 and 8, to serialize a dictionary you'll have to use a value converter.

@MacMcDell
Copy link
Author

MacMcDell commented Jul 16, 2023 via email

@roji
Copy link
Member

roji commented Jul 16, 2023

Yes.

@ajcvickers
Copy link
Contributor

Duplicate of #29825

@ajcvickers ajcvickers marked this as a duplicate of #29825 Jul 26, 2023
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Jul 26, 2023
@vchirikov
Copy link

@ajcvickers it's not a weakly-typed mapping. Seems like I ran into the same issue with strongly typed ImmutableDictionary :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants