简体   繁体   中英

System.Text.Json.JsonException: Unable to convert Json to DataModel

I'm attempting to seed data into a database from a json file but I keep running into the same error. As shown below in stack trace. I have an AppQuestion class and an IncorrectAnswer class. The data is meant to match these models and pass into my database. When attempting to Deserialize it seems like the Seed Incorrect array is causing the error. I would prefer to use System.Text.Json instead of Newsoft. Is there a way to process the data and stay true to my models.

SeedData.json:

[
{
  "Question": "Question1",
  "Incorrect": ["Answer1", "Answer2", "Answer3"],
  "Correct": "Answer4"
},
{
  "Question": "Question2",
  "Incorrect": ["Answer1", "Answer2", "Answer4"],
  "Correct": "Answer3"
}
]

C# Code

public class Seed
{
    public static async Task SeedQuestions(DataContext context)
    {
        if (await context.Questions.AnyAsync()) return;

        var questionData = await System.IO.File.ReadAllTextAsync("Data/QuestionSeedData.json");

        var questions = JsonSerializer.Deserialize<List<AppQuestion>>(questionData);
        foreach(var question in questions)
        {
            context.Questions.Add(question);
        }

        await context.SaveChangesAsync();
    }
}

public class AppQuestion
{
    
    public int Id { get; set; }
    public string Question { get; set; }
    public ICollection<IncorrectAnswer> Incorrect { get; set; }
    public string Correct { get; set; }
}


public class IncorrectAnswer
{
    public int Id { get; set; }

    public string Incorrect { get; set; }
    public AppQuestion AppQuestion { get; set; }

    public int AppQuestionId { get; set; }
}


public class DataContext : DbContext
{
    public DataContext( DbContextOptions options) : base(options)
    {
    }
    public DbSet<AppQuestion> Questions {get; set;}

    public DbSet<AppUser> Users { get; set; }
}
public class Program
{
    public static async Task Main(string[] args)
    {
        var host = CreateHostBuilder(args).Build();
        using var scope = host.Services.CreateScope();
        var services = scope.ServiceProvider;
        try
        {
            var context = services.GetRequiredService<DataContext>();
            await context.Database.MigrateAsync();
            await Seed.SeedQuestions(context);
        }
        catch (Exception ex)
        {
            var logger = services.GetRequiredService<ILogger<Program>>();
            logger.LogError(ex, "An error occurred during migration");
        }
        await host.RunAsync();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureWebHostDefaults(webBuilder =>
            {
                webBuilder.UseStartup<Startup>();
            });
}

Stack Trace:

fail: API.Program[0]
  An error occurred during migration
  System.Text.Json.JsonException: The JSON value could not be converted to API.Entities.IncorrectAnswer. Path: $[0].Incorrect[0] | LineNumber: 3 | BytePositionInLine: 28.
     at System.Text.Json.ThrowHelper.ThrowJsonException_DeserializeUnableToConvertValue(Type propertyType)
     at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
     at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
     at System.Text.Json.Serialization.Converters.IEnumerableDefaultConverter`2.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, TCollection& value)
     at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
     at System.Text.Json.JsonPropertyInfo`1.ReadJsonAndSetMember(Object obj, ReadStack& state, Utf8JsonReader& reader)
     at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
     at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
     at System.Text.Json.Serialization.Converters.IEnumerableDefaultConverter`2.OnTryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, TCollection& value)
     at System.Text.Json.Serialization.JsonConverter`1.TryRead(Utf8JsonReader& reader, Type typeToConvert, JsonSerializerOptions options, ReadStack& state, T& value)
     at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
     at System.Text.Json.JsonSerializer.ReadCore[TValue](JsonConverter jsonConverter, Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
     at System.Text.Json.JsonSerializer.ReadCore[TValue](Utf8JsonReader& reader, Type returnType, JsonSerializerOptions options)
     at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, Type returnType, JsonSerializerOptions options)
     at System.Text.Json.JsonSerializer.Deserialize[TValue](String json, JsonSerializerOptions options)
     at API.Data.Seed.SeedQuestions(DataContext context) in C:\Users\fahua\Documents\TriviaTandem\API\Data\Seed.cs:line 20
     at API.Program.Main(String[] args) in C:\Users\fahua\Documents\TriviaTandem\API\Program.cs:line 26

Incorrect property in AppQuestion class is a collection of IncorrectAnswer objects, but in your json incorrect is array of strings.

You either need to change your model or json.

In the end, I found a page mentioning explicitly stating the DataMember in attributes. I think seeding data should have a cleaner result, but this works for now.

public class Example
{
    [DataMember(Name="Question")]
    public string Question  { get; set; }

    [DataMember(Name="Incorrect")]
    public IList<string> Incorrect { get; set; }

    [DataMember(Name="Correct")]
    public string Correct { get; set; }
}


public class Seed
{
    public Seed()
    {
    }

    public static async Task SeedQuestions(DataContext context)
    {
        if (await context.Questions.AnyAsync()) return;

        var questionData = await System.IO.File.ReadAllTextAsync("Data/QuestionSeedData.json");

        var myDeserializedClass = JsonSerializer.Deserialize<List<Example>>(questionData);
        

        foreach (var item in myDeserializedClass)
        {
            var appQuestion = new AppQuestion();
            var incorrectAnswerList = new List<IncorrectAnswer>();

            appQuestion.Question = item.Question;
            appQuestion.Correct = item.Correct;
            foreach (var thing in item.Incorrect)
            {
                var incorrectAnswer = new IncorrectAnswer();
                incorrectAnswer.Incorrect = thing;
                incorrectAnswerList.Add(incorrectAnswer);
            }
            appQuestion.Incorrect = incorrectAnswerList;

            context.Questions.Add(appQuestion);
        }
        await context.SaveChangesAsync();
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM