使用 Flurl 和 ASP.net Core 解析 Json 数据
Parsing Json Data With Flurl and ASP.net Core
不太确定我问这个问题的方式是否正确。但是我正在用 CRM 系统和 API 为我的大学做一个项目。
现在我发现 Flurl 可以帮助我执行 HTTP 请求。在我尝试将所有帐户添加到我的免费开发人员帐户到 salesforce 之前,它一直很好用(我添加了一些测试帐户)。我收到的 JSON 是这样的:
{
"objectDescribe": {
"activateable": false,
"createable": true,
"custom": false,
"customSetting": false,
"deletable": true,
"deprecatedAndHidden": false,
"feedEnabled": true,
"hasSubtypes": false,
"isSubtype": false,
"keyPrefix": "001",
"label": "Account",
"labelPlural": "Accounts",
"layoutable": true,
"mergeable": true,
"mruEnabled": true,
"name": "Account",
"queryable": true,
"replicateable": true,
"retrieveable": true,
"searchable": true,
"triggerable": true,
"undeletable": true,
"updateable": true,
"urls": {
"compactLayouts": "/services/data/v39.0/sobjects/Account/describe/compactLayouts",
"rowTemplate": "/services/data/v39.0/sobjects/Account/{ID}",
"approvalLayouts": "/services/data/v39.0/sobjects/Account/describe/approvalLayouts",
"defaultValues": "/services/data/v39.0/sobjects/Account/defaultValues?recordTypeId&fields",
"listviews": "/services/data/v39.0/sobjects/Account/listviews",
"describe": "/services/data/v39.0/sobjects/Account/describe",
"quickActions": "/services/data/v39.0/sobjects/Account/quickActions",
"layouts": "/services/data/v39.0/sobjects/Account/describe/layouts",
"sobject": "/services/data/v39.0/sobjects/Account"
}
},
"recentItems": [
{
"attributes": {
"type": "Account",
"url": "/services/data/v39.0/sobjects/Account/0015800000it9T3AAI"
},
"Id": "0015800000it9T3AAI",
"Name": "Test 5"
},
{
"attributes": {
"type": "Account",
"url": "/services/data/v39.0/sobjects/Account/0015800000it8eAAAQ"
},
"Id": "0015800000it8eAAAQ",
"Name": "Test 4"
},
{
"attributes": {
"type": "Account",
"url": "/services/data/v39.0/sobjects/Account/0015800000it8dbAAA"
},
"Id": "0015800000it8dbAAA",
"Name": "Test 3"
},
{
"attributes": {
"type": "Account",
"url": "/services/data/v39.0/sobjects/Account/0015800000it8dHAAQ"
},
"Id": "0015800000it8dHAAQ",
"Name": "Test 2"
},
{
"attributes": {
"type": "Account",
"url": "/services/data/v39.0/sobjects/Account/0015800000it8ciAAA"
},
"Id": "0015800000it8ciAAA",
"Name": "Test 1"
}
]
}
我收到的错误如下:
Request to https://eu6.salesforce.com/services/data/v39.0/sobjects/Account/ failed.
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IEnumerable`1[InHollandCRMAPI.Models.AccountItem]'
because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object.
JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'objectDescribe', line 1, position 18.
我也在此处找到了这个 link:
但我似乎无法用我的模型重新创建它:
public class AccountItem : ICRMItem
{
public Describe[] ObjectDescribe { get; set; }
public List<Recent> recentItems { get; set; }
public class Recent
{
public Attributes[] Attributes { get; set; }
public string Id { get; set; }
public string Name { get; set; }
}
public class Describe
{
public bool activateable { get; set; }
public bool createable { get; set; }
public bool custom { get; set; }
public bool customSetting { get; set; }
public bool deletable { get; set; }
public bool deprecatedAndHidden { get; set; }
public bool feedEnabled { get; set; }
public bool hasSubtypes { get; set; }
public bool isSubtype { get; set; }
public string keyPrefix { get; set; }
public string label { get; set; }
public string labelPlural { get; set; }
public bool layoutable { get; set; }
public bool mergeable { get; set; }
public bool mruEnabled { get; set; }
public string name { get; set; }
public bool queryable { get; set; }
public bool replicateable { get; set; }
public bool retrieveable { get; set; }
public bool searchable { get; set; }
public bool triggerable { get; set; }
public bool undeletable { get; set; }
public bool updateable { get; set; }
public Urls[] urls { get; set; }
}
}
最后这就是我代码中反序列化的方式
response = request.GetAsync();
responseData = await response.ReceiveJson<T>().ConfigureAwait(true);
编辑 我的控制器class 请求的来源:
[HttpGet("{CRM}")]
public IEnumerable<ICRMItem> Get(string CRM)
{
if(CRM == "SalesForce")
{
ICRMService AccountGetAll = new AccountService();
var Account = AccountGetAll.With<AccountItem>().GetAll().ResponseData();
return Account;
}
}
在@Todd Menier 之后他的改变
作为我在托德的消息中的回应,可耻的是它没有达到目的。我仍然收到此异常消息。
Request to https://eu6.salesforce.com/services/data/v39.0/sobjects/Account/ ailed. Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type
'System.Collections.Generic.IEnumerable`1[InHollandCRMAPI.Models.AccountItem]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>)
that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'objectDescribe', line 1, position 18.
编辑
Todd Menier 问我代码的路径,所以这里是:
在我调用之后,它会进入我的控制器
ICRMService AccountGetAll = new AccountService();
var Account = AccountGetAll.With<AccountItem>().GetAll().ResponseData();
return Account;
它进入我的服务后的位置:
public ICRMServiceWithResource<T> With<T>(bool beta = false) where T : ICRMItem
{
var Uri = "https://eu6.salesforce.com/services/data/v39.0/";
return new SalesForceServiceWithResource<T>()
{
Resource = Resources.Resources.GetResource<T>(),
Uri = Uri
};
}
然后获取资源
public class Resources
{
public const string Accounts = "sobjects/Account/";
public static string GetResource<T>() where T : ICRMItem
{
var type = typeof(T);
if (type == typeof(AccountItem)) return Accounts;
它进入我的 GetAll 函数
public ICRMResponse<IEnumerable<T>> GetAll()
{
return Get<IEnumerable<T>>();
}
如您所见,它进入了一个 get 函数
private ICRMResponse<TOut> Get<TOut>(string id = "")
{
return DoRequest<TOut>(Resource + id, "GET", null).Result;
}
从哪里进入 DoRequest:
public async Task<ICRMResponse<T>> DoRequest<T>(string url, string method, object body)
{
ICRMResponse<T> result;
try
{
GetCRM(AppConfig.Key);
var request = Authorise(url);
Task<HttpResponseMessage> response;
T responseData;
switch (method.ToLower())
{
case "post":
if (body == null)
{
throw new ArgumentNullException("body");
}
response = request.PostJsonAsync(body);
responseData = await response.ReceiveJson<T>().ConfigureAwait(false);
break;
case "get":
response = request.GetAsync();
responseData = await response.ReceiveJson<T>().ConfigureAwait(true);
break;
从它中断的地方开始,并将消息显示为之前的状态
我会在 16:00 格林威治标准时间 +1 左右回来查看,否则周二早上希望我能给你你需要的一切
在你的C#模型中,urls
是一个数组,但它不是JSON表示中的数组;它是一个对象。
你没有 post 你的 Urls
class 的定义,但我猜它看起来像这样:
public class Urls
{
public string compactLayouts { get; set; }
public string rowTemplate { get; set; }
public string approvalLayouts { get; set; }
public string defaultValues { get; set; }
public string listviews { get; set; }
public string describe { get; set; }
public string quickActions { get; set; }
public string layouts { get; set; }
public string sobject { get; set; }
}
JSON 返回一个 单个 对象,看起来像这样,而不是它们的集合。因此,在您的 Describe
class 中,只需删除数组并像这样定义它:
public Urls urls { get; set; }
更新:
起初我没有看到,但 objectDescribe
和 attributes
也有类似的问题。这些也不是数组,所以不要在 C# 模型中以这种方式定义它们。以下是所有更改的摘要:
public class AccountItem : ICRMItem
{
public Describe ObjectDescribe { get; set; }
...
public class Recent
{
public Attributes Attributes { get; set; }
...
}
public class Describe
{
...
public Urls urls { get; set; }
}
}
Soo,我刚刚修复了错误。试图获取所有帐户的列表。但 salesforce 已经为您列出(部分)客户。
问题是 IEnumerable
在 GetAll()
函数中(对大多数 CRM 系统来说效果很好)但是如果你想完成这个,你需要将 IEnumerable<T>
更改为只是 T
,这将是 SalesForce
的快速修复
我的下一步是生成包含所有帐户信息的帐户列表(因为大多数 GetAll 使用 CRM API)。
TL;DR
public ICRMResponse<IEnumerable<T>> GetAll()
{
return Get<IEnumerable<T>>();
}
应该是
public ICRMResponse<T> GetAll() //Technicly isn't a GetAll But a Get
{
return DoRequest<T>(Resource, "GET", null).Result;
}
这是对此的修复 post 不是我最终愿望的修复,但我会关闭这个主题,否则我们会偏离主题
不太确定我问这个问题的方式是否正确。但是我正在用 CRM 系统和 API 为我的大学做一个项目。 现在我发现 Flurl 可以帮助我执行 HTTP 请求。在我尝试将所有帐户添加到我的免费开发人员帐户到 salesforce 之前,它一直很好用(我添加了一些测试帐户)。我收到的 JSON 是这样的:
{
"objectDescribe": {
"activateable": false,
"createable": true,
"custom": false,
"customSetting": false,
"deletable": true,
"deprecatedAndHidden": false,
"feedEnabled": true,
"hasSubtypes": false,
"isSubtype": false,
"keyPrefix": "001",
"label": "Account",
"labelPlural": "Accounts",
"layoutable": true,
"mergeable": true,
"mruEnabled": true,
"name": "Account",
"queryable": true,
"replicateable": true,
"retrieveable": true,
"searchable": true,
"triggerable": true,
"undeletable": true,
"updateable": true,
"urls": {
"compactLayouts": "/services/data/v39.0/sobjects/Account/describe/compactLayouts",
"rowTemplate": "/services/data/v39.0/sobjects/Account/{ID}",
"approvalLayouts": "/services/data/v39.0/sobjects/Account/describe/approvalLayouts",
"defaultValues": "/services/data/v39.0/sobjects/Account/defaultValues?recordTypeId&fields",
"listviews": "/services/data/v39.0/sobjects/Account/listviews",
"describe": "/services/data/v39.0/sobjects/Account/describe",
"quickActions": "/services/data/v39.0/sobjects/Account/quickActions",
"layouts": "/services/data/v39.0/sobjects/Account/describe/layouts",
"sobject": "/services/data/v39.0/sobjects/Account"
}
},
"recentItems": [
{
"attributes": {
"type": "Account",
"url": "/services/data/v39.0/sobjects/Account/0015800000it9T3AAI"
},
"Id": "0015800000it9T3AAI",
"Name": "Test 5"
},
{
"attributes": {
"type": "Account",
"url": "/services/data/v39.0/sobjects/Account/0015800000it8eAAAQ"
},
"Id": "0015800000it8eAAAQ",
"Name": "Test 4"
},
{
"attributes": {
"type": "Account",
"url": "/services/data/v39.0/sobjects/Account/0015800000it8dbAAA"
},
"Id": "0015800000it8dbAAA",
"Name": "Test 3"
},
{
"attributes": {
"type": "Account",
"url": "/services/data/v39.0/sobjects/Account/0015800000it8dHAAQ"
},
"Id": "0015800000it8dHAAQ",
"Name": "Test 2"
},
{
"attributes": {
"type": "Account",
"url": "/services/data/v39.0/sobjects/Account/0015800000it8ciAAA"
},
"Id": "0015800000it8ciAAA",
"Name": "Test 1"
}
]
}
我收到的错误如下:
Request to https://eu6.salesforce.com/services/data/v39.0/sobjects/Account/ failed.
Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IEnumerable`1[InHollandCRMAPI.Models.AccountItem]'
because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>) that can be deserialized from a JSON object.
JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'objectDescribe', line 1, position 18.
我也在此处找到了这个 link:
但我似乎无法用我的模型重新创建它:
public class AccountItem : ICRMItem
{
public Describe[] ObjectDescribe { get; set; }
public List<Recent> recentItems { get; set; }
public class Recent
{
public Attributes[] Attributes { get; set; }
public string Id { get; set; }
public string Name { get; set; }
}
public class Describe
{
public bool activateable { get; set; }
public bool createable { get; set; }
public bool custom { get; set; }
public bool customSetting { get; set; }
public bool deletable { get; set; }
public bool deprecatedAndHidden { get; set; }
public bool feedEnabled { get; set; }
public bool hasSubtypes { get; set; }
public bool isSubtype { get; set; }
public string keyPrefix { get; set; }
public string label { get; set; }
public string labelPlural { get; set; }
public bool layoutable { get; set; }
public bool mergeable { get; set; }
public bool mruEnabled { get; set; }
public string name { get; set; }
public bool queryable { get; set; }
public bool replicateable { get; set; }
public bool retrieveable { get; set; }
public bool searchable { get; set; }
public bool triggerable { get; set; }
public bool undeletable { get; set; }
public bool updateable { get; set; }
public Urls[] urls { get; set; }
}
}
最后这就是我代码中反序列化的方式
response = request.GetAsync();
responseData = await response.ReceiveJson<T>().ConfigureAwait(true);
编辑 我的控制器class 请求的来源:
[HttpGet("{CRM}")]
public IEnumerable<ICRMItem> Get(string CRM)
{
if(CRM == "SalesForce")
{
ICRMService AccountGetAll = new AccountService();
var Account = AccountGetAll.With<AccountItem>().GetAll().ResponseData();
return Account;
}
}
在@Todd Menier 之后他的改变
作为我在托德的消息中的回应,可耻的是它没有达到目的。我仍然收到此异常消息。
Request to https://eu6.salesforce.com/services/data/v39.0/sobjects/Account/ ailed. Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type
'System.Collections.Generic.IEnumerable`1[InHollandCRMAPI.Models.AccountItem]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List<T>)
that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'objectDescribe', line 1, position 18.
编辑
Todd Menier 问我代码的路径,所以这里是:
在我调用之后,它会进入我的控制器
ICRMService AccountGetAll = new AccountService();
var Account = AccountGetAll.With<AccountItem>().GetAll().ResponseData();
return Account;
它进入我的服务后的位置:
public ICRMServiceWithResource<T> With<T>(bool beta = false) where T : ICRMItem
{
var Uri = "https://eu6.salesforce.com/services/data/v39.0/";
return new SalesForceServiceWithResource<T>()
{
Resource = Resources.Resources.GetResource<T>(),
Uri = Uri
};
}
然后获取资源
public class Resources
{
public const string Accounts = "sobjects/Account/";
public static string GetResource<T>() where T : ICRMItem
{
var type = typeof(T);
if (type == typeof(AccountItem)) return Accounts;
它进入我的 GetAll 函数
public ICRMResponse<IEnumerable<T>> GetAll()
{
return Get<IEnumerable<T>>();
}
如您所见,它进入了一个 get 函数
private ICRMResponse<TOut> Get<TOut>(string id = "")
{
return DoRequest<TOut>(Resource + id, "GET", null).Result;
}
从哪里进入 DoRequest:
public async Task<ICRMResponse<T>> DoRequest<T>(string url, string method, object body)
{
ICRMResponse<T> result;
try
{
GetCRM(AppConfig.Key);
var request = Authorise(url);
Task<HttpResponseMessage> response;
T responseData;
switch (method.ToLower())
{
case "post":
if (body == null)
{
throw new ArgumentNullException("body");
}
response = request.PostJsonAsync(body);
responseData = await response.ReceiveJson<T>().ConfigureAwait(false);
break;
case "get":
response = request.GetAsync();
responseData = await response.ReceiveJson<T>().ConfigureAwait(true);
break;
从它中断的地方开始,并将消息显示为之前的状态
我会在 16:00 格林威治标准时间 +1 左右回来查看,否则周二早上希望我能给你你需要的一切
在你的C#模型中,urls
是一个数组,但它不是JSON表示中的数组;它是一个对象。
你没有 post 你的 Urls
class 的定义,但我猜它看起来像这样:
public class Urls
{
public string compactLayouts { get; set; }
public string rowTemplate { get; set; }
public string approvalLayouts { get; set; }
public string defaultValues { get; set; }
public string listviews { get; set; }
public string describe { get; set; }
public string quickActions { get; set; }
public string layouts { get; set; }
public string sobject { get; set; }
}
JSON 返回一个 单个 对象,看起来像这样,而不是它们的集合。因此,在您的 Describe
class 中,只需删除数组并像这样定义它:
public Urls urls { get; set; }
更新:
起初我没有看到,但 objectDescribe
和 attributes
也有类似的问题。这些也不是数组,所以不要在 C# 模型中以这种方式定义它们。以下是所有更改的摘要:
public class AccountItem : ICRMItem
{
public Describe ObjectDescribe { get; set; }
...
public class Recent
{
public Attributes Attributes { get; set; }
...
}
public class Describe
{
...
public Urls urls { get; set; }
}
}
Soo,我刚刚修复了错误。试图获取所有帐户的列表。但 salesforce 已经为您列出(部分)客户。
问题是 IEnumerable
在 GetAll()
函数中(对大多数 CRM 系统来说效果很好)但是如果你想完成这个,你需要将 IEnumerable<T>
更改为只是 T
,这将是 SalesForce
我的下一步是生成包含所有帐户信息的帐户列表(因为大多数 GetAll 使用 CRM API)。
TL;DR
public ICRMResponse<IEnumerable<T>> GetAll()
{
return Get<IEnumerable<T>>();
}
应该是
public ICRMResponse<T> GetAll() //Technicly isn't a GetAll But a Get
{
return DoRequest<T>(Resource, "GET", null).Result;
}
这是对此的修复 post 不是我最终愿望的修复,但我会关闭这个主题,否则我们会偏离主题