locked
Blazor Server - deserializing an array of objects with System.Text.Json - The JSON value could not be converted to ..... RRS feed

  • Question

  • User379720387 posted

    The JSON value could not be converted to BtServer.Pages.RecordDetail+MyRecordDetails. Path: $ | LineNumber: 0 | BytePositionInLine: 1.

       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.JsonConverter`1.ReadCore(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 BtServer.Pages.RecordDetail.<OnInitializedAsync>d__12.MoveNext() in C:\Users\Robert\source\Repos\BtApiCore5\BtServer\Pages\RecordDetail.razor:line 92

    public class MyRecordDetails
        {
            public IEnumerable<RecordDetail> details { get; set; }   

    //tried this one too! same error message: public List<RecordDetail> details { get; set; } } protected override async Task OnInitializedAsync() { try { var httpClient = _clientFactory.CreateClient("ServerAPI"); httpClient.DefaultRequestHeaders.Add("Accept", "application/json"); var json = JsonSerializer.Serialize(recordDetails); var content = new StringContent(json); content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"); var options = new JsonSerializerOptions() { PropertyNamingPolicy = JsonNamingPolicy.CamelCase }; HttpResponseMessage response = await httpClient.GetAsync($"{baseUrl}/api/Record/DetailByClient/22/49/3"); string dtls = await response.Content.ReadAsStringAsync(); if (dtls is not null) { MyRecordDetails details = JsonSerializer.Deserialize<MyRecordDetails>(dtls, options); } else { //do something } } catch (Exception ex) { Console.WriteLine(ex.Message); } }

    dtls holds: 

    [
    {"TransactionId":1015,"CName":"Don","TDate":"May 9 2020 4:54PM","BDate":"May 9 2020 4:54PM","Initials":"JMC","IsBilled":false,"IsPaid":false,"SvcLevel":"R1"},
    {"TransactionId":988,"CName":"Don","TDate":"Jan 23 2020 3:13PM","BDate":"Mar 10 2020 11:17AM","Initials":"JMC","IsBilled":false,"IsPaid":false,"SvcLevel":"R1"},
    {"TransactionId":974,"CName":"Don","TDate":"Jan 22 2020 2:36PM","BDate":"Jan 22 2020 2:36PM","Initials":"JMC","IsBilled":false,"IsPaid":false,"SvcLevel":"R1"}
    ]

    Online deserializers have no problem deserializing dtls

    public class RecordDetail
        {
            public int TransactionId { get; set; }
            public string CName { get; set; }
            public string TDate { get; set; }
            public string BDate { get; set; }
            public string Initials { get; set; }
            public bool IsBilled { get; set; }
            public bool IsPaid { get; set; }
            public string SvcLevel { get; set; }
            
            //public List<ServiceItem> ServiceItems { get; set; }
            //public List<ShoeItem> ShoeItems { get; set; }
            //public List<FileItem> FileItems { get; set; }
            //public List<ImageItem> ImageItems { get; set; }
            //public List<NoteItem> NoteItems { get; set; }
            //public List<VoiceItem> VoiceItems { get; set; }
        }

    What am I doing wrong?

    Sunday, March 7, 2021 2:20 PM

Answers

  • User-943250815 posted

    Here is what I did:
    1) Place your JSON sample above in a text file
    2) Make a file with your class and a routine to read file and deserialize JSON into a List

    public class RecordDetail
      {
        public int TransactionId { get; set; }
        public string CName { get; set; }
        public string TDate { get; set; }
        public string BDate { get; set; }
        public string Initials { get; set; }
        public bool IsBilled { get; set; }
        public bool IsPaid { get; set; }
        public string SvcLevel { get; set; }
      }
    
    void ReadJSonFromFile()
    {
    string MyFile = @"C:\sample.json";
    string MyJsonStr = System.IO.File.ReadAllText(MyFile);
    List<RecordDetail> DetailsNoOptions = System.Text.Json.JsonSerializer.Deserialize<List<RecordDetail>>(MyJsonStr);
    var options = new System.Text.Json.JsonSerializerOptions() {PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase};
    List<RecordDetail> DetailsWithOptions = System.Text.Json.JsonSerializer.Deserialize<List<RecordDetail>>(MyJsonStr, options);
    }

    This results:
    DetailsNoOptions = 3 itens, data filled with values from Json;
    DetailsWithOptions = 3 itens, data filled with null

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, March 8, 2021 10:53 PM

All replies

  • User-943250815 posted

    Back to your original intention, collect to a List.
    Give a try to, your as is looks fine for a single record, but you are readind an array

    List<MyRecordDetails> details = JsonSerializer.Deserialize<List<MyRecordDetails>>(dtls, options);

    Sunday, March 7, 2021 3:09 PM
  • User379720387 posted

    List<MyRecordDetails> details = JsonSerializer.Deserialize<List<MyRecordDetails>>(dtls, options);

    Returns details which has 3 members, each of them null

    Sunday, March 7, 2021 3:37 PM
  • User-474980206 posted

    You don’t show the class definition of MyRecordDetails

    Sunday, March 7, 2021 4:38 PM
  • User379720387 posted

    @bruce (sqlwork)

    This is all I have for MyRecordDetails, don't know if I am missing something:

    public class MyRecordDetails
        {
            public IEnumerable<RecordDetail> details { get; set; }           
        }
    Sunday, March 7, 2021 4:46 PM
  • User-943250815 posted

    Oops, I mistyped my sample above, here the correct one, using it you should get a list with 3 elements and values filled correctly.
    But don´t use "options" other than values will not be filled

    List<RecordDetail> details = JsonSerializer.Deserialize<List<RecordDetail>>(dtls);

    Monday, March 8, 2021 11:51 AM
  • User753101303 posted

    Hi,

    Or

    MyRecordDetails details = new MyRecordDetails();details.details=JsonSerializer.Deserialize<List<RecordDetail>>(dtls);

    Your json is a list of RecordDetail and you are confusing this with MyRecordDetails which is a single object having a property which is a list of RecordDetail and which is perhaps not needed.

    .

    Monday, March 8, 2021 1:53 PM
  • User379720387 posted

    @jzero

    Without "options" it hangs and there are no exceptions shown in VS or in browser console

    @PatriceSc

    That maybe so, I don't know.  Nothing works at this point, just throwing code on the wall and hope something sticks. So far I have been able to produce 3 elements (which matches what it is supposed to find)  but each element is null.

    Monday, March 8, 2021 9:53 PM
  • User-943250815 posted

    Here is what I did:
    1) Place your JSON sample above in a text file
    2) Make a file with your class and a routine to read file and deserialize JSON into a List

    public class RecordDetail
      {
        public int TransactionId { get; set; }
        public string CName { get; set; }
        public string TDate { get; set; }
        public string BDate { get; set; }
        public string Initials { get; set; }
        public bool IsBilled { get; set; }
        public bool IsPaid { get; set; }
        public string SvcLevel { get; set; }
      }
    
    void ReadJSonFromFile()
    {
    string MyFile = @"C:\sample.json";
    string MyJsonStr = System.IO.File.ReadAllText(MyFile);
    List<RecordDetail> DetailsNoOptions = System.Text.Json.JsonSerializer.Deserialize<List<RecordDetail>>(MyJsonStr);
    var options = new System.Text.Json.JsonSerializerOptions() {PropertyNamingPolicy = System.Text.Json.JsonNamingPolicy.CamelCase};
    List<RecordDetail> DetailsWithOptions = System.Text.Json.JsonSerializer.Deserialize<List<RecordDetail>>(MyJsonStr, options);
    }

    This results:
    DetailsNoOptions = 3 itens, data filled with values from Json;
    DetailsWithOptions = 3 itens, data filled with null

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Monday, March 8, 2021 10:53 PM
  • User379720387 posted

    Ok, figured it out.

    I have a "view model" called RecordDetail.cs, you have seen it in this thread, it lives in the Web API project.

    I also have a RecordDetail.razor page, it lives in the Blazor Server project

    When you declare this:

    private List<RecordDetail> recorddetails;

    It is making  List<RecordDetails.blazor> apparently.  That fails silently, there are no warnings about ambiguity.

    Too many leaves up in the air, and focused on the wrong leaf (deserialization).

    Thanks all for contributing taking some of these leaves out of the air.

    Tuesday, March 9, 2021 3:43 AM