efcore icon indicating copy to clipboard operation
efcore copied to clipboard

JSON: Allow weakly-typed mapping via Dictionary

Open roji opened this issue 2 years ago • 2 comments

#28871 tracks weakly-typed JSON mapping via JsonDocument/JsonElement, where the JSON document schema varies and so a strongly-typed model isn't appropriate.

We can also allow simply mapping arbitrary Dictionary types - this corresponds to how many people use

  • This intersects with #28688 (primitive collections in JSON).
  • Both keys and values should support any valid JSON data type (string, int...).
  • However we could also support Dictionary<string, object>, to map an entire hierarchy. See #26903 on this (currently seemed blocked by property bag detection).
  • This should be supported at the top-level, so that the JSON object as a whole is mapped as a single dictionary (see e.g. this issue). This would mean supporting OwnsOne(x => x.Json, builder => { builder.ToJson(); }) where x.Json is a Dictionary.

roji avatar Dec 11 '22 11:12 roji

Duplicate of #29427

roji avatar Dec 12 '22 13:12 roji

Re-opening, since dictionary mapping was not covered by "primitive collections".

ajcvickers avatar Jul 15 '23 15:07 ajcvickers

Link to the "issue" should be in the docs at least, was difficult to find.. Is it planned for 9.0 release?

vchirikov avatar Mar 20 '24 14:03 vchirikov

@vchirikov the milestone generally expresses whether an issue is planned for a given release or not.

roji avatar Mar 20 '24 20:03 roji

I assume this would also meant support for ExtensionData and Dictionary<string, JsonElement> ?

onionhammer avatar Apr 18 '24 21:04 onionhammer

@onionhammer that would be a combination of this and #28871.

roji avatar Apr 19 '24 10:04 roji

@roji putting querying aside for now, JsonElement can already be saved/serialized as an entity property, but Dictionary<string, JsonElement> cannot;

onionhammer avatar Apr 19 '24 14:04 onionhammer

is this why this isn't working ?

modelBuilder.Entity<Account>()
            .OwnsOne(c => c.Settings, d =>
            {
                d.ToJson();
                d.OwnsOne(a => a.ShippingRateMarkups);
            }).HasKey(c => c.AccountId);

///////////////////////////////
public class Account
{
    public string AccountId { get; set; }
    public Settings Settings { get; set; }
}
            
public class Settings
{
    public Dictionary<string, decimal>? ShippingRateMarkups { get; set; }
}

what's the alternative solution?

bugproof avatar May 30 '24 23:05 bugproof

@bugproof supporting mapping Dictionary<string, decimal> to JSON is what this issue tracked.

As a workaround, if all you want to do is save and load it to the database, you can use a value converter to do the JSON serialization/deserialization yourself. But this won't support querying into it, etc.

roji avatar May 31 '24 09:05 roji

And how will it be stored? As JSON instead of JSONB? Yes I don't need complex queries with it, just load/save as settings dictionary isn't very complex.

bugproof avatar Jun 02 '24 17:06 bugproof

As JSON instead of JSONB?

It's up to you to configure that database column type, as always - see the docs.

roji avatar Jun 02 '24 18:06 roji