summaryrefslogtreecommitdiff
path: root/Xamarin.Forms.Pages/JsonDataSource.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Xamarin.Forms.Pages/JsonDataSource.cs')
-rw-r--r--Xamarin.Forms.Pages/JsonDataSource.cs147
1 files changed, 147 insertions, 0 deletions
diff --git a/Xamarin.Forms.Pages/JsonDataSource.cs b/Xamarin.Forms.Pages/JsonDataSource.cs
new file mode 100644
index 00000000..3be50e8a
--- /dev/null
+++ b/Xamarin.Forms.Pages/JsonDataSource.cs
@@ -0,0 +1,147 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using System.Threading.Tasks;
+using Newtonsoft.Json.Linq;
+
+namespace Xamarin.Forms.Pages
+{
+ public class JsonDataSource : BaseDataSource
+ {
+ readonly ObservableCollection<IDataItem> _dataItems = new ObservableCollection<IDataItem>();
+ Task _currentParseTask;
+ bool _initialized;
+ JsonSource _source;
+
+ public JsonDataSource()
+ {
+ }
+
+ internal JsonDataSource(JToken rootToken)
+ {
+ ParseJsonToken(rootToken);
+ }
+
+ [TypeConverter(typeof(JsonSourceConverter))]
+ public JsonSource Source
+ {
+ get { return _source; }
+ set
+ {
+ if (_source == value)
+ return;
+ _source = value;
+
+ _dataItems.Clear();
+ if (value != null && _initialized)
+ {
+ _currentParseTask = ParseJson();
+ _currentParseTask.ContinueWith(t => { throw t.Exception; }, TaskContinuationOptions.OnlyOnFaulted);
+ }
+ }
+ }
+
+ protected override async Task<IList<IDataItem>> GetRawData()
+ {
+ if (!_initialized)
+ {
+ Task task = _currentParseTask = ParseJson();
+ await task;
+ }
+ else if (_currentParseTask != null && _currentParseTask.IsCompleted == false)
+ await _currentParseTask;
+ return _dataItems;
+ }
+
+ protected override object GetValue(string key)
+ {
+ IDataItem target = _dataItems.FirstOrDefault(d => d.Name == key);
+ return target?.Value;
+ }
+
+ protected override bool SetValue(string key, object value)
+ {
+ IDataItem target = _dataItems.FirstOrDefault(d => d.Name == key);
+ if (target == null)
+ {
+ _dataItems.Add(new DataItem(key, value));
+ return true;
+ }
+ if (target.Value == value)
+ return false;
+ target.Value = value;
+ return true;
+ }
+
+ object GetValueForJToken(JToken token)
+ {
+ switch (token.Type)
+ {
+ case JTokenType.Object:
+ case JTokenType.Array:
+ return new JsonDataSource(token);
+ case JTokenType.Constructor:
+ case JTokenType.Property:
+ case JTokenType.Comment:
+ throw new NotImplementedException();
+ case JTokenType.Integer:
+ return (int)token;
+ case JTokenType.Float:
+ return (float)token;
+ case JTokenType.Raw:
+ case JTokenType.String:
+ return (string)token;
+ case JTokenType.Boolean:
+ return (bool)token;
+ case JTokenType.Date:
+ return (DateTime)token;
+ case JTokenType.Bytes:
+ return (byte[])token;
+ case JTokenType.Guid:
+ return (Guid)token;
+ case JTokenType.Uri:
+ return (Uri)token;
+ case JTokenType.TimeSpan:
+ return (TimeSpan)token;
+ default:
+ return null;
+ }
+ }
+
+ async Task ParseJson()
+ {
+ _initialized = true;
+
+ if (Source == null)
+ return;
+
+ IsLoading = true;
+ string json = await Source.GetJson();
+ JToken jToken = JToken.Parse(json);
+ ParseJsonToken(jToken);
+ IsLoading = false;
+ }
+
+ void ParseJsonToken(JToken token)
+ {
+ var jArray = token as JArray;
+ var jObject = token as JObject;
+ if (jArray != null)
+ {
+ for (var i = 0; i < jArray.Count; i++)
+ {
+ JToken obj = jArray[i];
+ _dataItems.Add(new DataItem(i.ToString(), GetValueForJToken(obj)));
+ }
+ }
+ else if (jObject != null)
+ {
+ foreach (KeyValuePair<string, JToken> kvp in jObject)
+ {
+ _dataItems.Add(new DataItem(kvp.Key, GetValueForJToken(kvp.Value)));
+ }
+ }
+ }
+ }
+} \ No newline at end of file