1

I have a postgres table with a jsonb column. This jsonb column has an object with an enum in it. The db stores the enum as text.

However EF seems to use system.text.json to serialize/deserialize into the DB. I would like to use Newtonsoft.Json instead. But cannot find a way to achieve this

The reason i want to change is because system.text.json is less flexible. As you can see in the code below, system.text.json fails with a System.Text.Json.JsonException: The JSON value could not be converted to MyEnum. Path: $.Trigger | LineNumber: 0 | BytePositionInLine: 21. whilst newtonsoft.json works fine.

Can be replicated as below

public class Program
{
   public enum MyEnum { Hello=0, World }

   public class MyModel
    {
        public MyEnum Trigger { get; set; }
        public string Name { get; set; }
    }

    public static void Main()
    {
        
        var a =  @"{  ""Trigger"": ""Hello"",  ""Name"": ""Stack""}";//does not with system.text.json
        var b = @"{  ""Trigger"": 1,  ""Name"": ""Stack""}";//works     

        
        var newtonA = Newtonsoft.Json.JsonConvert.DeserializeObject<MyModel>(a);
        var newtonB = Newtonsoft.Json.JsonConvert.DeserializeObject<MyModel>(b);

        //var systemA = JsonSerializer.Deserialize<MyModel>(a); //uncomment for failure
        var systemB = JsonSerializer.Deserialize<MyModel>(b); 
         
        
        Console.WriteLine(newtonA.Trigger);
        Console.WriteLine(newtonB.Trigger);
        //Console.WriteLine(systemA.Trigger); //uncomment for failure
        Console.WriteLine(systemB.Trigger); 
        
    }
}

In my code i select from the DB as below.

public async Task<MyModel> GetMyModel(string id)
{
       IQueryable<MyModel> query = dbSet;

       query = query
           .Where(w => w.Id == id)

       var res = await query.SingleAsync();
       return res;
}

dbSet is a DbSet<TEntity>

Daniel Pace
  • 131
  • 1
  • 6
  • I have still not found a solution for the above. But I need to move on, so for now I updated the database to use the enum value rather than its string representation. But something i haven't mentioned, i also had another problem. Another jsonb column is anoymous (i have no type to cast it to) and system.text.json changes that to a string. From .Net6, system.text.json has a JsonObject class which works for these situations. In the meantime i hope somebody can come up with an answer for future use – Daniel Pace Oct 18 '22 at 12:57
  • You could apply `[System.Text.Json.Serialization.JsonConverter(typeof(JsonStringEnumConverter))]` directly to `MyEnum` as shown in [this answer](https://stackoverflow.com/a/69793672/3744182) by [schweppes0x](https://stackoverflow.com/users/17077257/schweppes0x) to [serialization of enum results in int](https://stackoverflow.com/q/69723923/3744182). If you do EF will serialize and deserialize your enum as a strring without needing to configure JsonSerializerOptions. – dbc Oct 18 '22 at 23:16
  • That being said, storing the enum value instead of the name in the DB is arguably preferable, as deserialization will not fail on unknown enum values. – dbc Oct 18 '22 at 23:19
  • *But something i haven't mentioned, i also had another problem...* then you should ask another question, as the preferred format here is [one question per post](https://meta.stackexchange.com/q/222735) – dbc Oct 18 '22 at 23:21

0 Answers0