这是我未解析的JSON:
{“1”:[[[2015,6,1,8,0,0,3600,“欧洲/伦敦”,“BST”,1],[ 2015年,6,1,9,30,0,3600,“欧洲/伦敦”,“BST”,1]],[[2015, 6,1,8,30,0,3600,“欧洲/伦敦”,“BST”,1],[2015,6,1,10, 0,0,3600,“欧洲/伦敦”,“BST”,1]],[[2015,6,1,9,0,0, 3600,“欧洲/伦敦”,“BST”,1],[2015,6,1,10,30,0,3600, “欧洲/伦敦”,“BST”,1]],[[2015,6,1,9,30,0,3600, “欧洲/伦敦”,“BST”,1],[2015,6,1,11,0,0,3600, “欧洲/伦敦”,“BST”,1]]],“2”:[[[2015,6,2,8,0,0,3600, “欧洲/伦敦”,“BST”,1],[2015,6,2,9,30,0,3600, “欧洲/伦敦”,“BST”,1]],[[2015,6,2,8,30,0,3600, “欧洲/伦敦”,“BST”,1],[2015,6,2,10,0,0,3600, “欧洲/伦敦”,“BST”,1]],[[2015,6,2,9,0,0,3600, “欧洲/伦敦”,“BST”,1],[2015,6,2,10,30,0,3600, “欧洲/伦敦”,“BST”,1]],[[2015,6,2,9,30,0,3600, “欧洲/伦敦”,“BST”,1],[2015,6,2,11,0,0,3600, “欧洲/伦敦”,“BST”,1]]],“3”:[[[2015,6,3,8,0,0,3600, “欧洲/伦敦”,“BST”,1],[2015,6,3,9,30,0,3600, “欧洲/伦敦”,“BST”,1]],[[2015,6,3,8,30,0,3600, “欧洲/伦敦”,“BST”,1],[2015,6,3,10,0,0,3600, “欧洲/伦敦”,“BST”,1]],[[2015,6,3,9,0,0,3600, “欧洲/伦敦”,“BST”,1],[2015,6,3,10,30,0,3600, “欧洲/伦敦”,“BST”,1]],[[2015,6,3,9,30,0,3600, “欧洲/伦敦”,“BST”,1],[2015,6,3,11,0,0,3600, “欧洲/伦敦”,“BST”,1]]],“4”:[[[2015,6,4,8,0,0,3600, “欧洲/伦敦”,“BST”,1],[2015,6,4,9,30,0,3600, “欧洲/伦敦”,“BST”,1]],[[2015,6,4,8,30,0,3600, “欧洲/伦敦”,“BST”,1],[2015,6,4,10,0,0,3600, “欧洲/伦敦”,“BST”,1]],[[2015,6,4,9,0,0,3600, “欧洲/伦敦”,“BST”,1],[2015,6,4,10,30,0,3600, “欧洲/伦敦”,“BST”,1]],[[2015,6,4,9,30,0,3600, “欧洲/伦敦”,“BST”,1],[2015,6,4,11,0,0,3600, “欧洲/伦敦”,“BST”,1]]]}
这是基本格式:
ROOT
Day of the month
time slot
time slot start
time slot end
这就是它的格式:
我无法弄清楚我的生活如何钻研这个。此问题应与How do I parse a JSON object in C# when I don't know the key in advance?
类似如果我执行以下操作,则会收到“System.InvalidOperationException:无法访问Newtonsoft.Json.Linq.JValue上的子值。”
JObject objTimes = JObject.Parse(strJson);
foreach (var day in objTimes["1"])
{
divTimes.InnerHtml += day[0][0][0];
}
答案 0 :(得分:0)
您可以做的是设计一个类(命名为Entry
)来表示代表JSON中最低级别数组的数据:[ 2015, 6, 3, 9, 30, 0, 3600, "Europe/London", "BST", 1 ]
。然后创建一个JsonConverter
以按顺序将数组值加载到数组中。最后根据需要反序列化外部字典和数组:
这是一个可能的类来表示单个内部数组的数据:
[JsonConverter(typeof(EntryConverter))]
public class Entry
{
public Entry()
{
// You need to determine whether the time numbers in the JSON are in UTC or in the timezone given in the "TimeZone" field. If
// Local, change to DateTimeKind.Local
DateTime = new DateTime(0, DateTimeKind.Utc);
}
public DateTime DateTime { get; set; }
public int Number { get; set; } // That 3600 thing. No idea what it's for.
public string Destination { get; set; }
public string TimeZone { get; set; }
// Not all time zone offsets are integers: https://en.wikipedia.org/wiki/UTC%E2%88%9204:30
public decimal GmtOffset { get; set; }
}
接下来,转换器:
public class EntryConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(Entry).IsAssignableFrom(objectType);
}
void SetField(Entry entry, int index, JValue value)
{
switch (index)
{
case 0:
entry.DateTime = new DateTime((int)value, entry.DateTime.Month, entry.DateTime.Day, entry.DateTime.Hour, entry.DateTime.Minute, entry.DateTime.Second, entry.DateTime.Millisecond, entry.DateTime.Kind);
break;
case 1:
entry.DateTime = new DateTime(entry.DateTime.Year, (int)value, entry.DateTime.Day, entry.DateTime.Hour, entry.DateTime.Minute, entry.DateTime.Second, entry.DateTime.Millisecond, entry.DateTime.Kind);
break;
case 2:
entry.DateTime = new DateTime(entry.DateTime.Year, entry.DateTime.Month, (int)value, entry.DateTime.Hour, entry.DateTime.Minute, entry.DateTime.Second, entry.DateTime.Millisecond, entry.DateTime.Kind);
break;
case 3:
entry.DateTime = new DateTime(entry.DateTime.Year, entry.DateTime.Month, entry.DateTime.Day, (int)value, entry.DateTime.Minute, entry.DateTime.Second, entry.DateTime.Millisecond, entry.DateTime.Kind);
break;
case 4:
entry.DateTime = new DateTime(entry.DateTime.Year, entry.DateTime.Month, entry.DateTime.Day, entry.DateTime.Hour, (int)value, entry.DateTime.Second, entry.DateTime.Millisecond, entry.DateTime.Kind);
break;
case 5:
entry.DateTime = new DateTime(entry.DateTime.Year, entry.DateTime.Month, entry.DateTime.Day, entry.DateTime.Hour, entry.DateTime.Minute, (int)value, entry.DateTime.Millisecond, entry.DateTime.Kind);
break;
case 6:
entry.Number = (int)value;
break;
case 7:
entry.Destination = (string)value;
break;
case 8:
entry.TimeZone = (string)value;
break;
case 9:
entry.GmtOffset = (decimal)value;
break;
default:
throw new IndexOutOfRangeException(index.ToString());
}
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var array = JArray.Load(reader);
if (array == null)
return existingValue;
var entry = (existingValue as Entry ?? new Entry());
for (int i = 0; i < array.Count; i++)
{
SetField(entry, i, (JValue)array[i]);
}
return entry;
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
然后使用它:
var root = JsonConvert.DeserializeObject<Dictionary<int, List<List<Entry>>>>(json);
Debug.WriteLine(JsonConvert.SerializeObject(root, Formatting.Indented));
虽然您可能不想这样做,但为了简明起见,我将所有时间信息压缩为单个DateTime
。此外,还不清楚时间信息是UTC还是当地时间。如果是本地的,那么我对DateTime.Kind
的使用是错误的。
如果需要,您可以扩展转换器以相同的顺序序列化字段。
答案 1 :(得分:0)
这是JSON.NET的一些松散实现。
首先是定义类。 TimeSlotInfo包含有关DayOfMonth和可用于该日期的时段的信息:
public class TimeSlotInfo
{
public int DayOfMonth { get; set; }
public List<TimeSlotRange> TimeSlots { get; set; }
public TimeSlotInfo()
{
TimeSlots = new List<TimeSlotRange>();
}
}
public class TimeSlotRange
{
public TimeSlotItem Start { get; set; }
public TimeSlotItem End { get; set; }
}
public class TimeSlotItem
{
public int Year { get; set; }
public int Month { get; set; }
public int Day { get; set; }
public int Hour { get; set; }
public int Minute { get; set; }
public int Second { get; set; }
public int SecondsInHour { get; set; }
public string TimezoneStr { get; set; }
public string BST { get; set; }
public int SomeNum { get; set; }
public DateTime AsDateTime
{
get { return new DateTime(Year, Month, Day, Hour, Minute, Second); }
}
public static TimeSlotItem CreateFromJTokenList(List<JToken> tokenList)
{
try
{
var result = new TimeSlotItem
{
Year = tokenList[0].Value<int>(),
Month = tokenList[1].Value<int>(),
Day = tokenList[2].Value<int>(),
Hour = tokenList[3].Value<int>(),
Minute = tokenList[4].Value<int>(),
Second = tokenList[5].Value<int>(),
SecondsInHour = tokenList[6].Value<int>(),
TimezoneStr = tokenList[7].Value<string>(),
BST = tokenList[8].Value<string>(),
SomeNum = tokenList[9].Value<int>()
};
return result;
}
catch (Exception)
{
return null;
}
}
}
然后你需要一个解析器来填充这些对象:
var timeSlotInfoList = new List<TimeSlotInfo>();
var jsonVal = System.IO.File.ReadAllText(@"C:\test.json"); // Somehow get JSON string into jsonVal. Not neccessarily from file.
var obj = JsonConvert.DeserializeObject(jsonVal) as JObject;
if (obj != null)
{
var jobj = obj.AsQueryable();
foreach (JProperty item in jobj)
{
try
{
var dayOfMonth = Convert.ToInt32(item.Name);
var timeSlotInfo = new TimeSlotInfo
{
DayOfMonth = dayOfMonth
};
timeSlotInfoList.Add(timeSlotInfo);
var timeSlots = item.Value.ToList();
foreach (var timeSlotPair in timeSlots)
{
var timeSlotPairList = timeSlotPair.ToList();
if (timeSlotPairList.Count != 2)
continue;
var slotItemStart = TimeSlotItem.CreateFromJTokenList(timeSlotPairList[0].ToList());
var slotItemEnd = TimeSlotItem.CreateFromJTokenList(timeSlotPairList[0].ToList());
if (slotItemStart != null && slotItemEnd != null)
{
timeSlotInfo.TimeSlots.Add(new TimeSlotRange
{
Start = slotItemStart,
End = slotItemEnd,
});
}
}
}
catch (Exception)
{
}
}
}
最后timeSlotInfoList
包含所有星期几及其时间段的列表(范围从开始到结束)。
此代码可能需要对异常,验证等进行更多调整,但这是解析此类内容的一些基本概念。 如果我犯了任何错误,我会对它有所评论。无论如何,希望它有所帮助。