Home > Back-end >  JsonSerializer.DeserializeAsync<T> no error, no exception, no result
JsonSerializer.DeserializeAsync<T> no error, no exception, no result

Time:01-28

In my NET MAUI application I am de-serializing a http response:

private async Task<T> SerializeResponse<T>(HttpContent content)
{
    var options = new JsonSerializerOptions
    {
        PropertyNameCaseInsensitive = true
    };

    using var stream = await content.ReadAsStreamAsync();
    var result = await JsonSerializer.DeserializeAsync<T>(stream, options);

    return result;
}

In this special case T is type of List, like:

public partial class BaseViewModel : ObservableValidator
{
    public event NotifyWithValidationMessages? ValidationCompleted;
    public virtual ICommand ValidateCommand => new RelayCommand(() => ValidateModel());

    public BaseViewModel()
    {
    }

    [IndexerName("ErrorDictionary")]
    public ValidationStatus this[string propertyName]
    {
        get
        {
            ValidateAllProperties();

            var errors = this.GetErrors()
                             .ToDictionary(k => k.MemberNames.First(), v => v.ErrorMessage) ?? new Dictionary<string, string?>();

            var hasErrors = errors.TryGetValue(propertyName, out var error);
            return new ValidationStatus(hasErrors, error ?? string.Empty);
        }
    }

    public void ValidateModel()
    {
        ValidateAllProperties();

        var validationMessages = this.GetErrors()
                                     .ToDictionary(k => k.MemberNames.First().ToLower(), v => v.ErrorMessage);

       ValidationCompleted?.Invoke(validationMessages);
    }
}

public partial class PlayerModel : BaseViewModel
{
    private int id;
    private string name;
    private string webImageLink;
    private string club;
    private string birthday;
    private string birthPlace;
    private int? weight;
    private double? height;
    private string description;
    private PositionModel position;
    
    public int Id
    {
        get => this.id;
        set => SetProperty(ref this.id, value, true);
    }

    [Required]
    [StringLength(255)]
    [MinLength(2)]
    public string Name
    {
        get => this.name;
        set
        {
            SetProperty(ref this.name, value, true);

            ClearErrors();
            ValidateAllProperties();
            OnPropertyChanged("ErrorDictionary[Name]");
        }
    }

    [Required]
    [StringLength(4096)]
    public string WebImageLink
    {
        get => this.webImageLink;
        set
        {
            SetProperty(ref this.webImageLink, value, true);

            ClearErrors();
            ValidateAllProperties();
            OnPropertyChanged("ErrorDictionary[WebImageLink]");
        }
    }

    [Required]
    [StringLength(255)]
    [MinLength(2)]
    public string Club
    {
        get => this.club;
        set
        {
            SetProperty(ref this.club, value, true);

            ClearErrors();
            ValidateAllProperties();
            OnPropertyChanged("ErrorDictionary[Club]");
        }
    }

    [Required]
    [StringLength(32)]
    public string Birthday
    {
        get => this.birthday;
        set
        {
            SetProperty(ref this.birthday, value, true);

            ClearErrors();
            ValidateAllProperties();
            OnPropertyChanged("ErrorDictionary[Birthday]");
        }
    }

    [Required]
    [StringLength(255)]
    public string BirthPlace
    {
        get => this.birthPlace;
        set
        {
            SetProperty(ref this.birthPlace, value, true);

            ClearErrors();
            ValidateAllProperties();
            OnPropertyChanged("ErrorDictionary[BirthPlace]");
        }
    }

    [Required]
    [Range(0, 100)]
    public int? Weight
    {
        get => this.weight;
        set
        {
            SetProperty(ref this.weight, value, true);

            ClearErrors();
            ValidateAllProperties();
            OnPropertyChanged("ErrorDictionary[Weight]");
        }
    }

    [Required]
    [Range(0, 2.5)]
    public double? Height
    {
        get => this.height;
        set
        {
            SetProperty(ref this.height, value, true);

            ClearErrors();
            ValidateAllProperties();
            OnPropertyChanged("ErrorDictionary[Height]");
        }
    }

    [Required]
    public string Description
    {
        get => this.description;
        set
        {
            SetProperty(ref this.description, value, true);

            ClearErrors();
            ValidateAllProperties();
            OnPropertyChanged("ErrorDictionary[Description]");
        }
    }

    [Required]
    public PositionModel Position
    {
        get => this.position;
        set
        {
            SetProperty(ref this.position, value, true);

            ClearErrors();
            ValidateAllProperties();
            OnPropertyChanged("ErrorDictionary[Position]");
        }
    }

    public PlayerModel() : base()
    {
    }

    public PlayerModel(int id, string name, string webImageLink, string club, string birthday, string birthPlace, int weight, double height, string description, string positionName, int positionId) : base()
    {
        Id = id;
        Name = name;
        WebImageLink = webImageLink;
        Club = club;
        Birthday = birthday;
        BirthPlace = birthPlace;
        Weight = weight;
        Height = height;
        Description = description;
        Position = new PositionModel(positionId, positionName);
    }

    public PlayerModel(int id, string name, string webImageLink, string club, string birthday, string birthPlace, int weight, double height, string description, PositionModel position) : base()
    {
        Id = id;
        Name = name;
        WebImageLink = webImageLink;
        Club = club;
        Birthday = birthday;
        BirthPlace = birthPlace;
        Weight = weight;
        Height = height;
        Description = description;
        Position = position;
    }

    public PlayerModel(PlayerEntity player)
    {
        Id = player.Id;
        Name = player.Name;
        WebImageLink = player.WebImageLink;
        Club = player.Club;
        Birthday = player.Birthday;
        BirthPlace = player.BirthPlace;
        Weight = player.Weight;
        Height = player.Height;
        Description = player.Description;
        Position = new PositionModel(player.Position);
    }

    public PlayerEntity ToEntity()
    {
        return new PlayerEntity
        {
            Id = Id,
            Name = Name,
            WebImageLink = WebImageLink,
            Club = Club,
            Birthday = Birthday,
            BirthPlace = BirthPlace,
            Weight = Weight.Value,
            Height = Height.Value,
            Description = Description,
            PositionId = Position.Id
        };
    }

    public void ToEntity(PlayerEntity player)
    {
        player.Id = Id;
        player.Name = Name;
        player.WebImageLink = WebImageLink;
        player.Club = Club;
        player.Birthday = Birthday;
        player.BirthPlace = BirthPlace;
        player.Weight = Weight.Value;
        player.Height = Height.Value;
        player.Description = Description;

        player.PositionId = Position.Id;
    }
}

I have a response from the server, the result is 200, there is content in the response, but when the line var result = await JsonSerializer.DeserializeAsync(stream, options); runs, no errors, no exception, no result, the code just stops.

thnx

UPDATE: So I tried the suggested

  • ReadAsStringAsync()
  • ReferenceHandler = ReferenceHandler.IgnoreCycles none worked.

When I deserialize to string, I got the following json as string:

[{"id":1,"name":"Nikola Radosová","webImageLink":"https://d3t3ozftmdmh3i.cloudfront.net/production/podcast_uploaded_episode/1378584/1378584-1567610413757-54d2f2d5dc6be.jpg","club":"FATUM Nyíregyháza","birthday":"1992.05.03","birthPlace":"Bojnice, Czechoslovakia","weight":66,"height":1.86,"description":"Nikola Radosová (born 3 May 1992) is a Slovak female volleyball player. She is part of the Slovakia women's national volleyball team. She competed at the 2019 Women's European Volleyball Championship.","position":{"id":1,"name":"outside hitter"},"validateCommand":{},"hasErrors":false},{"id":2,"name":"Tanja Matic","webImageLink":"https://brse.hu/wp-content/uploads/2022/07/Tanja-vote.jpg","club":"1. MCM-Diamant","birthday":"1983.03.21","birthPlace":"Subotica, Szerbia","weight":57,"height":1.79,"description":"Tanja Matic több száz szerb élvonalbeli mérkőzéssel a háta mögött, a patinás Szpartak Szabadka korábbi csapatkapitányaként 2015 nyarán érkezett hazánkba, és előbb két éven át játszott Békéscsabán, majd két szezont húzott le Nyíregyházán. A csabaiakkal mindent megnyert, amit csak itthon lehetett: a bajnokságban és a Magyar Kupában is két-két elsőséggel gazdagodott, emellett egy Közép-európai Liga elsőséget is begyűjtött. A nyíregyháziakkal két alkalommal hódította el a Magyar Kupa-trófeát, és 2018-ban, illetve 2019-ben is bejutott a bajnokság döntőjébe, ahol végül ezüstéremmel zárt. A tapasztalt röplabdázó ezek után, pályafutásának újabb állomásaként Kaposvárt választotta, így újra együtt dolgozhatott korábbi edzőjével, Sasa Nedeljkoviccsal. A 2019/2020-as évadban elért eredményekre mindenki büszke lehet, de mivel az ismert okok miatt váratlanul félbeszakadt, majd véget is ért a pontvadászat, mindenki kettőzött erővel szeretne majd újra munkába állni","position":{"id":2,"name":"opposite"},"validateCommand":{},"hasErrors":false}]

UPDATE 2: The method that calls deserialization:

protected async Task<T> SendGetRequestAsync<T>(string route, object routParam)
    {
        try
        {
            var uri = BuildUri(route, routParam);

            var response = await httpClient.GetAsync(uri);
            response.EnsureSuccessStatusCode();

            var content = await SerializeResponse<T>(response.Content);
            return content;

        }
        catch (Exception ex)
        {
            throw new Exception(ex.Message);
        }
    }

UPDATE 3: I just created a single console app, to find out what is wrong. I am getting an exception:

System.Text.Json.JsonException: ''S' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0.'.

The 'S' is not is, its something like $ sing, but it's not.

CodePudding user response:

You should add JsonSerializerOptions Referance Handler

Here your solution

new JsonSerializerOptions
{
  ReferenceHandler = ReferenceHandler.IgnoreCycles
}

var result = await JsonSerializer.DeserializeAsync<T>(stream, new JsonSerializerOptions
    {
      ReferenceHandler = ReferenceHandler.IgnoreCycles
    });

CodePudding user response:

forget about a stream

        using (var response = await client.PostAsync(api, requestContent))
        {       
                if (response.IsSuccessStatusCode)
                {
                var responseContent = await response.Content.ReadAsStringAsync();
                result = JsonConvert.DeserializeObject<T>(responseContent);
               } 
        }

the class you posted is too complicated and I am sure has not seriazible code. So I recommend you to create DTO like this one using online tool for example. This DTO is very short and simple, but it deserializes your json string properly. After this you can try to map DTO data to your classes. Or better you can find a lot code examples, that shows how to use DTO as a base class of the class that implements MVVM pattern

List<DTO> data = JsonConvert.DeserializeObject<List<DTO>>(json);

public partial class DTO
{
    [JsonProperty("id")]
    public long Id { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }

    [JsonProperty("webImageLink")]
    public Uri WebImageLink { get; set; }

    [JsonProperty("club")]
    public string Club { get; set; }

    [JsonProperty("birthday")]
    public string Birthday { get; set; }

    [JsonProperty("birthPlace")]
    public string BirthPlace { get; set; }

    [JsonProperty("weight")]
    public long Weight { get; set; }

    [JsonProperty("height")]
    public double Height { get; set; }

    [JsonProperty("description")]
    public string Description { get; set; }

    [JsonProperty("position")]
    public Position Position { get; set; }

    [JsonProperty("validateCommand")]
    public ValidateCommand ValidateCommand { get; set; }

    [JsonProperty("hasErrors")]
    public bool HasErrors { get; set; }
}

public partial class Position
{
    [JsonProperty("id")]
    public long Id { get; set; }

    [JsonProperty("name")]
    public string Name { get; set; }
}
public partial class ValidateCommand
{
}
  • Related