我目前正在编写一个应该轮询大量API的服务,尽可能统一数据,并将其存储在我的数据库中。我宁愿不必为每个请求创建一个新类,也不想为我想要保存的每个数据子集创建一个新类。所以我选择使用匿名和动态类型。这造成了以下怪物;可能是因为我很长时间没有使用匿名/动态类型。我还应该注意到这个功能不起作用,但应该对我想要实现的目标给出一个很好的要点。
public string GetActivities(ApplicationUser user)
{
//TODO: get statistics of today. If exists, overwrite.
var date = DateTime.Today;
var apiCall = String.Format("/1/user/-/activities/date/{0}.json", date.ToString("yyyy-MM-dd"));
var request = new RestRequest(apiCall);
var response = restClient.Execute(request);
//If the response is not what we expected (and exception gets thrown in HandleResponse), rethrow the exception.
try
{
HandleResponse(response);
}
catch
{
throw;
}
//Create a dynamic object from the JSON response. This way we do not need to create a new class for each response.
dynamic data = JsonConvert.DeserializeObject(response.Content);
//Create a list to add anonymous objects to. We define the prototype in Select()
var activities = Enumerable.Empty<dynamic>()
.Select(r => new {
distance = 0,
duration = 0,
hasStartTime = false,
startTime = DateTime.Now,
calories = 0,
steps = 0
}).ToList();
//Grab the data we need from the API response
foreach(var a in data.activities)
{
var act = new
{
distance = a.distance,
duration = a.duration,
hasStartTime = a.hasStartTime,
startTime = a.startTime,
calories = a.calories,
steps = a.steps
};
activities.Add(act);
}
List<Statistic> statistics = new List<Statistic>();
foreach (var a in activities)
{
var parsedData = new { distance = "" };
//Add the data we received as a JSON object to the object we store in the database.
var statistic = new Statistic()
{
ID = Guid.NewGuid(),
Device = context.Device.Where(d => d.Name == "Fitbit").Single(),
Timestamp = DateTime.Today,
Type = context.StatisticType.Where(s => s.Type == "calories_eaten").Single(),
User = user,
Value = JsonConvert.SerializeObject(parsedData)
};
statistics.Add(statistic);
}
//Save the newly added data to the database.
context.Statistic.AddRange(statistics);
context.SaveChanges();
return null;
}
考虑到这个功能已经变得怪异,还有其他选择吗?最好是我不需要创建大量课程。
答案 0 :(得分:0)
你到底想要做什么?通过阅读您的代码,您似乎放弃了有关活动的所有数据。 JSON影响代码的唯一方法是活动数量。
这是:
var parsedData = new { distance = "" };
实际上应该这样说:
var parsedData = new { distance = a.distance };
如果您只对您阅读的JSON中的一个值感兴趣,我建议使用JSON.net LINQ会更简单。这是一个将JSON视为一堆字典的接口(称为&#34;对象&#34;与JS保持一致,对象实际上是一个字典)和数组,就像JSON一样。
JObject data = JObject.Parse(response.Content);
JArray activities = (JArray)data["activities"];
foreach (JToken activity in activities)
{
JObject activityObject = (JObject)activity;
JObject parsedData = new JObject();
parsedData["distance"] = activityObject["distance"];
var statistic = new Statistic()
{
...
Value = parsedData.ToString();
}
...
}
答案 1 :(得分:0)
我可能会错过您要执行的操作,但如果您使用的是MVC,则无需创建空动态Enumerable。您应该能够将您带回的原始数据本身迭代到您可以在“模型”文件夹中创建的单个“活动”模型中:
public class Activity {
public int distance { get; set; };
public int duration { get; set; };
public bool hasStartTime { get; set; };
public DateTime startTime { get; set; };
public int calories { get; set; };
public int steps { get; set; };
}
然后:
List<Statistic> statistics = new List<Statistic>();
IEnumerable<Activity> data = JsonConvert.DeserializeObject(response.Content);
foreach(var a in data)
{
statistics.Add( new Statistic()
{
ID = Guid.NewGuid(),
Device = context.Device.Where(d => d.Name == "Fitbit").Single(),
Timestamp = DateTime.Today,
Type = context.StatisticType.Where(s => s.Type == "calories_eaten").Single(),
User = user,
Value = JsonConvert.SerializeObject(parsedData)
Distance = a.distance,
Duration = a.duration,
StartTime = a.startTime,
Calories = a.calories,
Steps = a.steps
});
}
return statistics; // or do whatever you were going to do with this, here