首页 > 解决方案 > 反序列化对象不返回 Xamarin.Forms 中的完整数据

问题描述

我有一个基于用户键入的关键字返回的 JSON 对象。它只返回用户输入的一些关键字。当我检查邮递员并输入相同的关键字时,它会正确返回。

引发以下异常:

Newtonsoft.Json.JsonSerializationException: 
Must specify valid information for parsing in the string

JSON

{
  "valid": true,
  "result": {
    "points": [
      {
        "pointId": "505",
        "name": "Building one",
        "description": "Office of Technology and Data Application Development",
        "latitude": "xxx",
        "longitude": "xxx",
        "floor": "B",
        "aliases": [],
        "comments": [],
        "images": []
      }
    ],
    "categories": []
  },
  "errors": []
}

模型类

public class SearchPoints
{
    public bool Valid { get; set; }
    public Result Result { get; set; }
    public List<string> Errors { get; set; }
}

public class Result
{
    public List<Point> Points { get; set; }
    public List<Category> Categories { get; set; }
}

public class Category
{
  public long CategoryId { get; set; }
  public string Name { get; set; }
  public long ParentId { get; set; }
  public string Parent { get; set; }
}

public class Point
{
    public long PointId { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public string Latitude { get; set; }
    public string Longitude { get; set; }
    public Floor Floor { get; set; }
    public List<string> Aliases { get; set; }
    public List<string> Comments { get; set; }
    public List<string> Images { get; set; }
}

public enum Floor 
{ 
    A, 
    B 
};

服务方式

var apiResponse = await _httpClient.GetAsync(Url + _keyword);
var apiContent = apiResponse.Content.ReadAsStringAsync().Result;
var pointsJsonResponse = JsonConvert.DeserializeObject<SearchPoints>(apiContent);

var potentialPoints = new ObservableCollection<Point>(pointsJsonResponse.Result.Points);

PointsItemSource = potentialPoints;

标签: c#xamarin.formsjson.net

解决方案


您问题中显示的 JSON 成功反序列化为问题中显示的数据模型,请参阅https://dotnetfiddle.net/nDhNPL

但是,您的问题中显示的异常提供了一些信息。根据搜索,(有些不透明)消息必须指定用于解析字符串中的有效信息仅在 Json.NET 源中出现一次,特别是在:EnumUtils.ParseEnum(Type enumType, NamingStrategy? namingStrategy, string value, bool disallowNumber)

public static object ParseEnum(Type enumType, NamingStrategy? namingStrategy, string value, bool disallowNumber)
{

// SNIP

    if (firstNonWhitespaceIndex == -1)
    {
        throw new ArgumentException("Must specify valid information for parsing in the string.");
    }

enum如果在解析字符串时,传入的值仅包含空格,则相关代码将引发异常。因此,我将您问题中的 JSON 修改如下:

    "floor": " ",

并复制了此处所示的异常:https ://dotnetfiddle.net/6zaG9W 。

因此,您实际上必须尝试使用​​空值或空格值解析 JSONFloor并失败,因为这是不可能的。要完成这项工作,您可以:

  1. 更改Point.Floor为字符串:

    public string Floor { get; set; }
    

    JSON 现在将成功解析。演示小提琴在这里:https ://dotnetfiddle.net/zg5YWr 。

  2. 使用StringEnumConverter处理空字符串的特殊子类FloorDavor ZlotrgHow to handle deserialization of empty string into enum in json.net回答中显示了一个示例,我在这里对其进行概括:

    public class EmptyTolerantStringEnumConverter : StringEnumConverter
    {
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.String && string.IsNullOrWhiteSpace(reader.Value.ToString()))
                // Return a default value.  Note if deserializing a nullable enum the default value is null
                return Activator.CreateInstance(objectType);
    
            return base.ReadJson(reader, objectType, existingValue, serializer);
        }       
    }
    

    并按如下方式应用:

    [JsonConverter(typeof(EmptyTolerantStringEnumConverter))]
    public Floor Floor { get; set; }
    

    或者,如果您更喜欢映射""到可为空的:

    [JsonConverter(typeof(EmptyTolerantStringEnumConverter))]
    public Floor? Floor { get; set; }
    

    演示小提琴在这里:https ://dotnetfiddle.net/DwGKHU

相关:如何在全局范围内告诉 Json.Net 将 StringEnumConverter 应用于所有枚举解析 JSON.net 中的枚举


推荐阅读