【问题标题】:Extract JSON info and put into object提取 JSON 信息并放入对象
【发布时间】:2018-03-28 16:50:42
【问题描述】:

到目前为止,我的服务使用填充的 JSON 得到了有效响应。我的问题是我应该如何解析 JSON 以便将 pAnn 放入我的对象中。我正在设计它以供将来可能使用,以防我需要将此 JSON 中的更多值分配给对象。如果有更简单的方法来解决这个问题,请告诉我。

public IEnumerable<CP> GetP()
{
    string pURL, getPResult;
    var handler = new HttpClientHandler();

    handler.Credentials = new NetworkCredential("username", "password");

    using (HttpClient client = new HttpClient(handler))
    {
        pURL = String.Concat(validurl + 5854);
        client.BaseAddress = new Uri(pURL);                
        HttpResponseMessage result = client.GetAsync(client.BaseAddress).Result;       

        if (!result.IsSuccessStatusCode)
        {
            throw new WebException();
        }
        else
        {
            getPResult = result.Content.ReadAsStringAsync().Result;
        }                 

        var pDetails = JsonConvert.DeserializeObject<List<CP>>(getPResult);

        IEnumerable<CP> pResults = from cOpt in pDetails
                                                      select new CP
                                                      {
                                                          pAnn = cO.pAnn
                                                      };
        return pResults;
    }
}

这是我的对象:

public class CP
{
    public string pAnn { get; set; }
}

这是我返回的 JSON 信息:

{"data":{.... "cO":[{..... "pAnn":11111.11 .... },"errorMessages":[],"success":true}

JsonConvert.DeserializeObject 行出现错误:

Newtonsoft.Json.JsonSerializationException 发生 Message=Cannot 将当前 JSON 对象(例如 {"name":"value"})反序列化为 type 'System.Collections.Generic.List 因为该类型需要 JSON 数组(例如 [1,2,3])以正确反序列化。修复此错误 将 JSON 更改为 JSON 数组(例如 [1,2,3])或更改 反序列化类型,使其成为普通的 .NET 类型(例如,不是 像整数这样的原始类型,而不是像数组这样的集合类型或 List) 可以从 JSON 对象反序列化。 JsonObjectAttribute 也可以添加到类型中以强制它 从 JSON 对象反序列化。

【问题讨论】:

标签: c# .net json asp.net-core


【解决方案1】:

您遇到的错误很明确。您获得的 JSON 有一个对象,您正试图将其反序列化为列表 List&lt;CoveragePremium&gt;。我会告诉你删除List&lt;&gt;

var premiumDetails = JsonConvert.DeserializeObject<CoveragePremium>(getPremiumResult);

但这不起作用,因为您的 CoveragePremium 类与您获得的 JSON 对象不匹配。两者必须匹配,否则反序列化会失败。如果你不想要errorMessagessuccess,而只关心coverageOptions 中的premiumAnnual,那么你至少需要创建这些类和属性:

public class RootObject {
    public Data data { get; set; }
}

public class Data {
    public List<CoverageOption> coverageOptions { get; set; }
    //If you want to include the other properties, uncomment the lines below:
    //public List<string> errorMessages { get; set; }
    //public bool success { get; set; }
}

public class CoverageOption {
    public decimal premiumAnnual { get; set; }
}

现在您可以将您的线路更改为:

var premiumDetails = JsonConvert.DeserializeObject<RootObject>(getPremiumResult);

但是,在您的 LINQ 中,您将 premiumAnnual 选择到 CoveragePremium 对象中,该对象的 premiumAnnualstring。最好将其更改为 decimal,这样您以后可以将该值用作数字而不是字符串:

public class CoveragePremium {
    public decimal premiumAnnual { get; set; }
}

【讨论】:

    【解决方案2】:

    您的数据示例结构是有效的 json 格式。

    {"data":{"coverageOptions":[{"premiumAnnual":11257.9284 }],"errorMessages":[],"success":true}}
    

    我想你的样本喜欢上面。

    public class CoveragePremium
    {
        public string premiumAnnual { get; set; }
    }
    
    public class CoverageOption
    {
        public double premiumAnnual { get; set; }
    }
    
    public class Data
    {
        public List<CoverageOption> coverageOptions { get; set; }
        public List<string> errorMessages { get; set; }
        public bool success { get; set; }
    }
    
    public class ResultObject
    {
        public Data data { get; set; }
    }
    
    static void Main(string[] args)
    {
        string getPremiumResult = "{\"data\":{\"coverageOptions\":[{\"premiumAnnual\":11257.9284 }],\"errorMessages\":[],\"success\":true}}";
        var result = JsonConvert.DeserializeObject<ResultObject>(getPremiumResult);
    
        IEnumerable<CoveragePremium> premiumResults = from value in result.data.coverageOptions
                                                          select new CoveragePremium
                                                          {
                                                              premiumAnnual = value.premiumAnnual.ToString(CultureInfo.InvariantCulture)
                                                          };
    
        Console.ReadKey();
    }
    

    我希望这个结构能满足你的需要

    【讨论】:

    • CultureInfo.InvariantCulture 应该在最后参考什么?
    • 如果将CoveragePremium.premiumAnnual 更改为doubledecimal,则不需要ToString(CultureInfo.InvariantCulture)`。答案中有它的原因是从double 转换为string
    • @RacilHilan 说得对。如果您将CoveragePremium.premiumAnnual 更改为双精度或十进制,则不需要ToString,但我不想更改您的返回类型。因此,我必须将双精度转换为字符串。我将我的 IDE 配置为自动添加 CultureInfo.InvariantCulture。开发和生产环境有时文化不同,因此我通常尝试使用 InvariantCulture 选项执行转换/转换操作。您也可以使用ToString()
    【解决方案3】:

    为避免在 .NET 中创建 JSON 类时出错,您可以复制 JSON 文件并转到 Visual Studio=>Edit=>Paste Special=>Paste JSON as classes。完成后,它会将您的 JSON 格式文件转换为类:

    public class Rootobject
    {
        public Data data { get; set; }
    }
    
    public class Data
    {
        public Coverageoption[] coverageOptions { get; set; }
        public object[] errorMessages { get; set; }
        public bool success { get; set; }
    }
    
    public class Coverageoption
    {
        public float premiumAnnual { get; set; }
    }
    
    
    string yourJsonString= "{"data":{"coverageOptions":[{"premiumAnnual":11257.9284 }],"errorMessages":[],"success":true}}";
    var result = JsonConvert.DeserializeObject<Rootobject>(yourJsonString);
    

    现在您可以通过以下方式访问您的数据:

    var ifSuccess = result.data.success;
    var coverageOption = result.data.coverageOptions[0].premiumAnnual;
    

    【讨论】:

    • 这与其他答案一起完美。感谢您帮助我!
    猜你喜欢
    • 1970-01-01
    • 2020-10-07
    • 2021-10-17
    • 1970-01-01
    • 2015-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多