如何将API Json响应转换为C#数组?

问题描述 投票:0回答:4

我正在用 C# 编写一个 Web 服务。为此,我正在对 PVGIS 进行 API 调用。此API文档用于每月太阳辐射值指定它使用基本文本数据或CSV数据进行响应,但API响应在任何情况下都会提供表格视图。我需要将此响应转换为 C# 数组或对象。

我已经尝试了人们在回答其他类似问题时指定的所有方法。

API响应:

Latitude (decimal degrees): 45.000
Longitude (decimal degrees):    8.000
Radiation database: PVGIS-CMSAF
Optimal slope angle (deg.): 

Year         Month      Hh
2005        Jan     56.5
2005        Feb     75.7
2005        Mar     118
2005        Apr     131
2005        May     193
2005        Jun     211
2005        Jul     217
2005        Aug     179
2005        Sep     115
2005        Oct     72.9
2005        Nov     42.4
2005        Dec     39.4
2006        Jan     51.3
2006        Feb     58.6
2006        Mar     118
2006        Apr     147
2006        May     167
2006        Jun     215
...

我正在使用这段代码


    JavaScriptSerializer ser = new JavaScriptSerializer();
    string json = ser.Serialize(response.Content);

我得到的回应是

"Latitude (decimal degrees):\t0.000\r\nLongitude (decimal degrees):\t0.000\r\nRadiation database:\tPVGIS-CMSAF\r\nOptimal slope angle (deg.):\t\r\n\r\nYear\t\t Month\t\tHh\r\n2005\t\tJan\t\t0\r\n2005\t\tFeb\t\t0\r\n2005\t\tMar\t\t0\r\n2005\t\tApr\t\t0\r\n2005\t\tMay\t\t0\r\n2005\t\tJun\t\t0\r\n2005\t\tJul\t\t0\r\n2005\t\tAug\t\t0\r\n2005\t\tSep\t\t0\r\n2005\t\tOct\t\t0\r\n2005\t\tNov\t\t0\r\n2005\t\tDec\t\t0\r\n2006\t\tJan\t\t0\r\n2006\t\tFeb\t\t0\r\n2006\t\tMar\t\t0\r\n2006\t\tApr\t\t0\r\n2006\t\tMay\t\t0\r\n2006\t\tJun\t\t0\r\n2006\t\tJul\t\t0\r\n2006\t\tAug\t\t0\r\n2006\t\tSep\t\t0\r\n2006\t\tOct\t\t0\r\n2006\t\tNov\t\t0\r\n2006\t\tDec\t\t0\r\n2007\t\tJan\t\t0\r\n2007\t\tFeb\t\t0\r\n2007\t\tMar\t\t0\r\n2007\t\tApr\t\t0\r\n2007\t\tMay\t\t0\r\n2007\t\tJun\t\t0\r\n2007\t\tJul\t\t0\r\n2007\t\tAug\t\t0\r\n2007\t\tSep\t\t0\r\n2007\t\tOct\t\t0\r\n2007\t\tNov\t\t0\r\n2007\t\tDec\t\t0\r\n2008\t\tJan\t\t0\r\n2008\t\tFeb\t\t0\r\n2008\t\tMar\t\t0\r\n2008\t\tApr\t\t0\r\n2008\t\tMay\t\t0\r\n2008\t\tJun\t\t0\r\n2008\t\tJul\t\t0\r\n2008\t\tAug\t\t0\r\n2008\t\tSep\t\t0\r\n2008\t\tOct\t\t0\r\n2008\t\tNov\t\t0\r\n2008\t\tDec\t\t0\r\n2009\t\tJan\t\t0\r\n2009\t\tFeb\t\t0\r\n2009\t\tMar\t\t0\r\n2009\t\tApr\t\t0\r\n2009\t\tMay\t\t0\r\n2009\t\tJun\t\t0\r\n2009\t\tJul\t\t0\r\n2009\t\tAug\t\t0\r\n2009\t\tSep\t\t0\r\n2009\t\tOct\t\t0\r\n2009\t\tNov\t\t0\r\n2009\t\tDec\t\t0\r\n2010\t\tJan\t\t0\r\n2010\t\tFeb\t\t0\r\n2010\t\tMar\t\t0\r\n2010\t\tApr\t\t0\r\n2010\t\tMay\t\t0\r\n2010\t\tJun\t\t0\r\n2010\t\tJul\t\t0\r\n2010\t\tAug\t\t0\r\n2010\t\tSep\t\t0\r\n2010\t\tOct\t\t0\r\n2010\t\tNov\t\t0\r\n2010\t\tDec\t\t0\r\n2011\t\tJan\t\t0\r\n2011\t\tFeb\t\t0\r\n2011\t\tMar\t\t0\r\n2011\t\tApr\t\t0\r\n2011\t\tMay\t\t0\r\n2011\t\tJun\t\t0\r\n2011\t\tJul\t\t0\r\n2011\t\tAug\t\t0\r\n2011\t\tSep\t\t0\r\n2011\t\tOct\t\t0\r\n2011\t\tNov\t\t0\r\n2011\t\tDec\t\t0\r\n2012\t\tJan\t\t0\r\n2012\t\tFeb\t\t0\r\n2012\t\tMar\t\t0\r\n2012\t\tApr\t\t0\r\n2012\t\tMay\t\t0\r\n2012\t\tJun\t\t0\r\n2012\t\tJul\t\t0\r\n2012\t\tAug\t\t0\r\n2012\t\tSep\t\t0\r\n2012\t\tOct\t\t0\r\n2012\t\tNov\t\t0\r\n2012\t\tDec\t\t0\r\n2013\t\tJan\t\t0\r\n2013\t\tFeb\t\t0\r\n2013\t\tMar\t\t0\r\n2013\t\tApr\t\t0\r\n2013\t\tMay\t\t0\r\n2013\t\tJun\t\t0\r\n2013\t\tJul\t\t0\r\n2013\t\tAug\t\t0\r\n2013\t\tSep\t\t0\r\n2013\t\tOct\t\t0\r\n2013\t\tNov\t\t0\r\n2013\t\tDec\t\t0\r\n2014\t\tJan\t\t0\r\n2014\t\tFeb\t\t0\r\n2014\t\tMar\t\t0\r\n2014\t\tApr\t\t0\r\n2014\t\tMay\t\t0\r\n2014\t\tJun\t\t0\r\n2014\t\tJul\t\t0\r\n2014\t\tAug\t\t0\r\n2014\t\tSep\t\t0\r\n2014\t\tOct\t\t0\r\n2014\t\tNov\t\t0\r\n2014\t\tDec\t\t0\r\n2015\t\tJan\t\t0\r\n2015\t\tFeb\t\t0\r\n2015\t\tMar\t\t0\r\n2015\t\tApr\t\t0\r\n2015\t\tMay\t\t0\r\n2015\t\tJun\t\t0\r\n2015\t\tJul\t\t0\r\n2015\t\tAug\t\t0\r\n2015\t\tSep\t\t0\r\n2015\t\tOct\t\t0\r\n2015\t\tNov\t\t0\r\n2015\t\tDec\t\t0\r\nHh: Irradiation on horizontal plane  (kWh/m2)\r\n\r\nPVGIS (c) European Communities, 2001-2016"

我希望输出是可以转换为 C# 对象的 JSON 对象,或者如果可能的话,将响应直接转换为 C# 数组或对象。

c# arrays json api web-services
4个回答
2
投票

一些网络服务以多种格式呈现数据。因此,http 请求可以说明它需要哪种数据类型,并且 Web 服务将以该格式提供数据。 https://restfulapi.net/content-negotiation/

对于你的问题,我认为如果你将标头“Accept:application/json”添加到你的http请求中,Web服务将为你提供json格式的数据。


0
投票

哇,如果您可以请求 API 以 json 或 xml 进行响应,您可以轻松完成此工作 - 但如果它确实只是表格文本,那么生活会变得有点复杂,因为您需要手动解析数据并将其转换为物体。

让我们考虑一个您可能定位的示例对象,其中包含另一种自定义类型的集合。 (为了方便起见,我们使用了列表,因为我们可能不知道预期数据的长度,如果愿意,您可以用它替换 HashSet,或者甚至稍微交换一下,使其成为一个私有集合,并使用将其作为数组返回的公共方法如果数组是您需要使用的等等。您也可以根据需要更改成员类型)。

public class ApiData
{
    public decimal Latitude { get; set; }
    public decimal Longitude { get; set; }
    public string RadiationDatabase { get; set; }
    public List<ApiSlopeAngle> OptimalSlopeAngle { get; set; }

    public ApiData()
    {
        OptimalSlopeAngle = new List<ApiSlopeAngle>();
    }
}

这是嵌套对象。

public class ApiSlopeAngle
{
    public int Year { get; set; }
    public string Month { get; set; }
    public decimal Hh { get; set; }
    public ApiSlopeAngle(int year, string month, decimal hh)
    {
        Year = year;
        Month = month;
        Hh = hh;
    }
}

这是一些缩短的示例数据。

// Sample data
string apiStringData = "Latitude (decimal degrees):\t45.000\r\nLongitude (decimal degrees):\t8.000\r\nRadiation database:\tPVGIS-CMSAF\r\nOptimal slope angle (deg.):\t\r\n\r\nYear\t\t Month\t\tHh\r\n2005\t\tJan\t\t56.5\r\n2005\t\tFeb\t\t75.7\r\n2005\t\tMar\t\t118\r\n2005\t\tApr\t\t131\r\n2005\t\tMay\t\t193\r\n2005\t\tJun\t\t211\r\n2005\t\tJul\t\t217\r\n2005\t\tAug\t\t179\r\n2005\t\tSep\t\t115\r\n2005\t\tOct\t\t72.9\r\n2005\t\tNov\t\t42.4\r\nHh: Irradiation on horizontal plane(kWh/ m2)\r\n\r\nPVGIS(c) European Communities, 2001 - 2016";

现在使用正则表达式解析示例数据...免责声明 - 代码仅作为示例,并且包含假设数据格式一致的最少检查。而且我的正则表达式非常基本!

// Define the regex patterns to use
string lattPattern = "(Latitude\\s\\(decimal\\sdegrees\\):)(\\t\\d+\\.*\\d*)";
string longPattern = "(Longitude\\s\\(decimal\\sdegrees\\):)(\\t\\d+\\.*\\d*)";
string radDbPattern = "(Radiation\\sdatabase\\:)(\\t)(PVGIS\\-CMSAF)";
string osaPattern = "((19|20)\\d{2})(\\t\\t)([A-Z]+[a-z]*)(\\t\\t\\d+\\.*\\d*)";

// Create the matches for the top-level data
var lattitude = Regex.Match(apiStringData, lattPattern);
var longitude = Regex.Match(apiStringData, longPattern);
var radDb = Regex.Match(apiStringData, radDbPattern);

// Create the result object, and populate the top-level properties
ApiData apiObject = new ApiData();
apiObject.Latitude = Convert.ToDecimal(lattitude.Groups[2].ToString());
apiObject.Longitude = Convert.ToDecimal(longitude.Groups[2].ToString());
apiObject.RadiationDatabase = radDb.Groups[3].ToString();

// Split the sample data into an array 
// to make it easier to enumerate what will become the nested data
string[] apiArray = Regex.Split(apiStringData, "\r\n");

// Step through it
foreach (string s in apiArray)
{
    var angle = Regex.Match(s, osaPattern, RegexOptions.IgnoreCase);
    if (angle.Success == true)
    {
        // Create the properties
        int year = Convert.ToInt32(angle.Groups[1].ToString());
        string month = angle.Groups[4].ToString();
        decimal hh = Convert.ToDecimal(angle.Groups[5].ToString());

        // Add to the collection
        ApiSlopeAngle apiDate = new ApiSlopeAngle(year, month, hh);
        apiObject.OptimalSlopeAngle.Add(apiDate);
    }
}

再次强调,这里还有很大的改进空间,很高兴任何人都能做得更好!


0
投票

鉴于您已经在使用 ToObject,请考虑简化代码以提高可读性以及无需转换任何内容的优点,您可以在您的情况下创建一个具有 3 个属性的类并使用此代码( 您应该记住,字段是根据 Json 输出使用类属性构建的):

你的班级:

  public class Monthly
    {
        public string Year { get; set; }
        public string Month { get; set; }
        public string  Hh { get; set; }
    }

var contentJson = await SendRequest(request);
dynamic response = JsonConvert.DeserializeObject(contentJson); 
List<Monthly> organizations = response.organizations.ToObject<List<Monthly>>();

实际响应似乎并不重要,因此使用动态可以简化事情。通过调用 ToObject 转换回强类型对象是一个不错的选择,应该效果很好。


0
投票

清洁解决方案:

对于 C# 使用这种方式

  JArray jsondata = (JArray)JsonConvert.DeserializeObject(APIResponse);
© www.soinside.com 2019 - 2024. All rights reserved.