I have a dictionary of strings and object that i obtained deserializing this json answer:
{"labels":[{"id":"1","descrizione":"Etichetta interna","tipo":"0","template_file":"et_int.txt"},{"id":"2","descrizione":"Etichetta esterna","tipo":"1","template_file":"et_ext.txt"}],"0":200,"error":false,"status":200}
using the code:
var labels = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(json);
Now i want to loop only trought the objects inside the "labels" key.
I tried
foreach (var outer in labels["labels"]){/* code */}
but i got error:
CS1579: foreach statement cannot operate on variables of type 'object' because 'object' does not contain a public definition for 'GetEnumerator'.
Solved replacing the dictionary with a class, thank you
Create a class to deserialize your json:
To create classes, you can copy the json in clipboard and use the
Edit / Paste special / Paste JSON as class
in visual studio (I use vs2013).
[TestMethod]
public void test()
{
string json = "{\"labels\" : [{\"id\" : \"1\",\"descrizione\" : \"Etichetta interna\",\"tipo\" : \"0\",\"template_file\" : \"et_int.txt\"}, {\"id\" : \"2\",\"descrizione\" : \"Etichetta esterna\",\"tipo\" : \"1\",\"template_file\" : \"et_ext.txt\"}],\"0\" : 200,\"error\" : false,\"status\" : 200}";
var root = JsonConvert.DeserializeObject<Rootobject>(json);
foreach (var label in root.Labels)
{
//Use label.Id, label.Descrizione, label.Tipo, label.TemplateFile
}
}
public class Rootobject
{
public Label[] Labels { get; set; }
public int _0 { get; set; }
public bool Error { get; set; }
public int Status { get; set; }
}
public class Label
{
public string Id { get; set; }
public string Descrizione { get; set; }
public string Tipo { get; set; }
public string TemplateFile { get; set; }
}
You need to loop through your dictionary.
foreach(KeyValuePair<string, Object> entry in labels)
{
// do something with entry.Value or entry.Key
}
Once you start looping through it you will get access to key and value. Since you are interested to look at entry.value you can do operation on that easily. Currently your dictionary value is type of object which does not have an enumerator
Your problem is that you've defined the Type of Value for each dictionary entry as object. C# can't know how to loop over on object. So you need to work out what type is actually inside the object once the JavaScriptSerializer have parsed the JSON. One way is
var t = typeof(labels["labels"]);
Once you know what type the serializer is creating, all you need to do is cast the object back to that type. For example, assuming it's a list of objects
var labels = (List<object>)labels["labels"];
foreach (var label in labels)
{
}
Alternatively, if each object in the JSON is the same, you could try create the dictionary as the type you need. So you serializing becomes
var labels = new JavaScriptSerializer()
.Deserialize<Dictionary<string, List<object>>>(json);
A possible solution:
static void Main(string[] args) {
string json = #"{'labels':[{'id':'1','descrizione':'Etichetta interna','tipo':'0','template_file':'et_int.txt'},{'id':'2','descrizione':'Etichetta esterna','tipo':'1','template_file':'et_ext.txt'}],'0':200,'error':false,'status':200}";
var labels = new JavaScriptSerializer().Deserialize<Dictionary<string, object>>(json);
IEnumerable inner_labels = labels["labels"] as IEnumerable;
if (inner_labels != null) {
foreach (var outer in inner_labels) {
Console.WriteLine(outer);
}
}
}
Otherwise, you can create a class with deserialization information and instruct the deserializer to deserialize your json string to that type:
using System;
using System.Collections.Generic;
using System.Web.Script.Serialization;
using System.Xml.Serialization;
[Serializable]
public class JsonData {
[XmlElement("labels")]
public List<JsonLabel> labels { get; set; }
[XmlElement("0")]
public int zero { get; set; }
[XmlElement("error")]
public bool error { get; set; }
[XmlElement("status")]
public int status { get; set; }
}
[Serializable]
public class JsonLabel {
[XmlElement("id")]
public int id { get; set; }
[XmlElement("descrizione")]
public string descrizione { get; set; }
[XmlElement("tipo")]
public int tipo { get; set; }
[XmlElement("template_file")]
public string template_file { get; set; }
}
class Program {
static void Main(string[] args) {
string json = #"your json string here...";
var jsonData = new JavaScriptSerializer().Deserialize<JsonData>(json);
foreach (var label in jsonData.labels) {
Console.WriteLine(label.id);
}
}
}
Could you please try below snippet?
It might be help you.
foreach (var item in labels["labels"] as ArrayList)
{
Console.Write(item);
}
Related
I have following Json-based configuration file:
{
"PostProcessing": {
"ValidationHandlerConfiguration": {
"MinimumTrustLevel": 80,
"MinimumMatchingTrustLevel": 75
},
"MatchingCharacterRemovals": [
"-",
"''",
":"
]
},
"Processing": {
"OrderSelection": {
"SelectionDaysInterval": 30,
"SelectionDaysMaximum": 365
}
}
}
As serialization framework I use Newtonsoft. To serialize this config into objects I have implemented following classes:
[JsonObject(MemberSerialization.OptIn)]
public class RecognitionConfiguration {
[JsonProperty(PropertyName = "PostProcessing", Required = Required.Always)]
public PostRecognitionConfiguration PostRecognitionConfiguration { get; set; }
[JsonProperty(PropertyName = "Processing", Required = Required.Always)]
public ProcessRecognitionConfiguration ProcessRecognitionConfiguration { get; set; }
}
[JsonObject(MemberSerialization.OptIn)]
public class PostRecognitionConfiguration {
[JsonProperty(Required = Required.Always)]
public ValidationHandlerConfiguration ValidationHandlerConfiguration { get; set; }
[JsonProperty] public List<string> MatchingCharacterRemovals { get; set; }
}
[JsonObject(MemberSerialization.OptIn)]
public class ProcessRecognitionConfiguration {
[JsonProperty(PropertyName = "OrderSelection", Required = Required.Always)]
public OrderSelectionConfiguration OrderSelectionConfiguration { get; set; }
}
In a class I try to serialize a specific configuration section into these class structures using IConfigurationSection.Get().
var serializedConfiguration = this.ConfigurationSection.Get<RecognitionConfiguration>();
But when I debug the code, I always get an "empty" variable serializedConfiguration which is not null, but all properties are null.
If I use
this.ConfigurationSection.GetSection("Processing").Get<ProcessRecognitionConfiguration>()
or change the naming of the properties in the json file to exactly match the property names in the classes like this:
{
"ProcessRecognitionConfiguration": {
"OrderSelectionConfiguration": {
"SelectionDaysInterval": 30,
"SelectionDaysMaximum": 365
}
}
}
it it works fine. Do you have any idea, why setting PropertyName on JsonProperty does not seem to have any effect?
That is by design. Binding to POCO via configuration is done by convention. Not like Model Binding to Controller Action parameters.
It matches property names on the POCO to keys in the provided JSON.
Reference Configuration in ASP.NET Core
So either you change the settings to match the class like you showed in the original question, or change the class to match the settings keys in the Json-based configuration file.
[JsonObject(MemberSerialization.OptIn)]
public class RecognitionConfiguration {
[JsonProperty(PropertyName = "PostProcessing", Required = Required.Always)]
public PostRecognitionConfiguration PostProcessing{ get; set; }
[JsonProperty(PropertyName = "Processing", Required = Required.Always)]
public ProcessRecognitionConfiguration Processing{ get; set; }
}
[JsonObject(MemberSerialization.OptIn)]
public class PostRecognitionConfiguration {
[JsonProperty(Required = Required.Always)]
public ValidationHandlerConfiguration ValidationHandlerConfiguration { get; set; }
[JsonProperty]
public List<string> MatchingCharacterRemovals { get; set; }
}
[JsonObject(MemberSerialization.OptIn)]
public class ProcessRecognitionConfiguration {
[JsonProperty(PropertyName = "OrderSelection", Required = Required.Always)]
public OrderSelectionConfiguration OrderSelection { get; set; }
}
public partial class ValidationHandlerConfiguration {
[JsonProperty("MinimumTrustLevel")]
public long MinimumTrustLevel { get; set; }
[JsonProperty("MinimumMatchingTrustLevel")]
public long MinimumMatchingTrustLevel { get; set; }
}
public partial class OrderSelectionConfiguration {
[JsonProperty("SelectionDaysInterval")]
public long SelectionDaysInterval { get; set; }
[JsonProperty("SelectionDaysMaximum")]
public long SelectionDaysMaximum { get; set; }
}
EDIT: I found this one is much more pleasant than my previous solutions: Bind everything in an ExpandoObject, write them to JSON and use JSON.NET to bind them back. Using the code of this article:
namespace Microsoft.Extensions.Configuration
{
public static class ConfigurationBinder
{
public static void BindJsonNet(this IConfiguration config, object instance)
{
var obj = BindToExpandoObject(config);
var jsonText = JsonConvert.SerializeObject(obj);
JsonConvert.PopulateObject(jsonText, instance);
}
private static ExpandoObject BindToExpandoObject(IConfiguration config)
{
var result = new ExpandoObject();
// retrieve all keys from your settings
var configs = config.AsEnumerable();
foreach (var kvp in configs)
{
var parent = result as IDictionary<string, object>;
var path = kvp.Key.Split(':');
// create or retrieve the hierarchy (keep last path item for later)
var i = 0;
for (i = 0; i < path.Length - 1; i++)
{
if (!parent.ContainsKey(path[i]))
{
parent.Add(path[i], new ExpandoObject());
}
parent = parent[path[i]] as IDictionary<string, object>;
}
if (kvp.Value == null)
continue;
// add the value to the parent
// note: in case of an array, key will be an integer and will be dealt with later
var key = path[i];
parent.Add(key, kvp.Value);
}
// at this stage, all arrays are seen as dictionaries with integer keys
ReplaceWithArray(null, null, result);
return result;
}
private static void ReplaceWithArray(ExpandoObject parent, string key, ExpandoObject input)
{
if (input == null)
return;
var dict = input as IDictionary<string, object>;
var keys = dict.Keys.ToArray();
// it's an array if all keys are integers
if (keys.All(k => int.TryParse(k, out var dummy)))
{
var array = new object[keys.Length];
foreach (var kvp in dict)
{
array[int.Parse(kvp.Key)] = kvp.Value;
}
var parentDict = parent as IDictionary<string, object>;
parentDict.Remove(key);
parentDict.Add(key, array);
}
else
{
foreach (var childKey in dict.Keys.ToList())
{
ReplaceWithArray(input, childKey, dict[childKey] as ExpandoObject);
}
}
}
}
}
Usage:
var settings = new MySettings();
this.Configuration.BindJsonNet(settings);
Here is my testing MySettings class:
public class MySettings
{
[JsonProperty("PostProcessing")]
public SomeNameElseSettings SomenameElse { get; set; }
public class SomeNameElseSettings
{
[JsonProperty("ValidationHandlerConfiguration")]
public ValidationHandlerConfigurationSettings WhateverNameYouWant { get; set; }
public class ValidationHandlerConfigurationSettings
{
[JsonProperty("MinimumTrustLevel")]
public int MinimumTrustLevelFoo { get; set; }
[JsonProperty("MinimumMatchingTrustLevel")]
public int MinimumMatchingTrustLevelBar { get; set; }
}
}
}
After the calling, I get everything as you desired:
Old Answer:
According to the source code here, it is simply (near) impossible to do what you are requiring. I have tried both JsonProperty and DataContract, none of which are honored by the Binder, simply because the source code itself simply use the property name.
If you still insist, there are 2 possibilities, however I do not recommend any as changing properties' names are much simpler:
Fork your source code there, or simply copy that file (in my attempt to trace the code, I rename all methods to something like Bind2, BindInstance2 etc), and rewrite the code accordingly.
This one is very specific to current implementation, so it's not future-proof: the current code is calling config.GetSection(property.Name), so you can write your own IConfiguration and provide your own name for GetSection method and tap it into the bootstrap process instead of using the default one.
Changing PropertyName on JsonProperty does have effect. Here is the same I tried and it did worked for me:
my JSON data:
{"name": "John","age": 30,"cars": [ "Ford", "BMW", "Fiat" ]}
and the Model:
public class RootObject
{
[JsonProperty(PropertyName ="name")]
public string Apple { get; set; }
public int age { get; set; }
public List<string> cars { get; set; }
}
and here is the code:
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
and this is the output i get
You need to set the PropertyName in JsonProperty same as json file property name but your C# model property can be what you wanted, just that they need to be decorated with [JsonProperty(PropertyName ="jsonPropertyName")] Hope this helps you solve your issue.
Happy coding...
I have a class MyClass. I would like to convert this to a dynamic object so I can add a property.
This is what I had hoped for:
dynamic dto = Factory.Create(id);
dto.newProperty = "123";
I get the error:
WEB.Models.MyClass does not contain a definition for 'newProperty'
Is that not possible?
The following has worked for me in the past:
It allows you to convert any object to an Expando object.
public static dynamic ToDynamic<T>(this T obj)
{
IDictionary<string, object> expando = new ExpandoObject();
foreach (var propertyInfo in typeof(T).GetProperties())
{
var currentValue = propertyInfo.GetValue(obj);
expando.Add(propertyInfo.Name, currentValue);
}
return expando as ExpandoObject;
}
Based on: http://geekswithblogs.net/Nettuce/archive/2012/06/02/convert-dynamic-to-type-and-convert-type-to-dynamic.aspx
As my object has JSON specific naming, I came up with this as an alternative:
public static dynamic ToDynamic(this object obj)
{
var json = JsonConvert.SerializeObject(obj);
return JsonConvert.DeserializeObject(json, typeof(ExpandoObject));
}
For me the results worked great:
Model:
public partial class Settings
{
[JsonProperty("id")]
public int Id { get; set; }
[JsonProperty("runTime")]
public TimeSpan RunTime { get; set; }
[JsonProperty("retryInterval")]
public TimeSpan RetryInterval { get; set; }
[JsonProperty("retryCutoffTime")]
public TimeSpan RetryCutoffTime { get; set; }
[JsonProperty("cjisUrl")]
public string CjisUrl { get; set; }
[JsonProperty("cjisUserName")]
public string CjisUserName { get; set; }
[JsonIgnore]
public string CjisPassword { get; set; }
[JsonProperty("importDirectory")]
public string ImportDirectory { get; set; }
[JsonProperty("exportDirectory")]
public string ExportDirectory { get; set; }
[JsonProperty("exportFilename")]
public string ExportFilename { get; set; }
[JsonProperty("jMShareDirectory")]
public string JMShareDirectory { get; set; }
[JsonIgnore]
public string Database { get; set; }
}
I used it in this manner:
private static dynamic DynamicSettings(Settings settings)
{
var settingsDyn = settings.ToDynamic();
if (settingsDyn == null)
return settings;
settingsDyn.guid = Guid.NewGuid();
return settingsDyn;
}
And received this as a result:
{
"id": 1,
"runTime": "07:00:00",
"retryInterval": "00:05:00",
"retryCutoffTime": "09:00:00",
"cjisUrl": "xxxxxx",
"cjisUserName": "xxxxx",
"importDirectory": "import",
"exportDirectory": "output",
"exportFilename": "xxxx.xml",
"jMShareDirectory": "xxxxxxxx",
"guid": "210d936e-4b93-43dc-9866-4bbad4abd7e7"
}
I don't know about speed, I mean it is serializing and deserializing, but for my use it has been great. A lot of flexability like hiding properties with JsonIgnore.
Note: xxxxx above is redaction. :)
You cannot add members to class instances on the fly.
But you can use ExpandoObject. Use factory to create new one and initialize it with properties which you have in MyClass:
public static ExpandoObject Create(int id)
{
dynamic obj = new ExpandoObject();
obj.Id = id;
obj.CreatedAt = DateTime.Now;
// etc
return obj;
}
Then you can add new members:
dynamic dto = Factory.Create(id);
dto.newProperty = "123";
You can't add properties to types at runtime. However, there is an exception which is: ExpandoObject. So if you need to add properties at runtime you should use ExpandoObject, other types don't support this.
Just to add up my experience, if you are using JSON.NET, then below might be one of the solution:
var obj....//let obj any object
ExpandoObject expandoObject= JsonConvert.DeserializeObject<ExpandoObject>(JsonConvert.SerializeObject(obj));
Not tested performances etc.. but works.
Trying to deserialize an array of book objects from the GoogleBook API.
Models: https://pastebin.com/24S16hZc
Confirmed API respons: https://pastebin.com/2q0aFGnf
Booking Page:
public BookingPage()
{
this.InitializeComponent();
ResizeWindow();
UpdateListView();
}
private void UpdateListView()
{
UserList_List.Items.Clear();
foreach (HelperLibrary.UserObject L in App.GlobalUserList)
{
UserList_List.Items.Add($" { L.FirstName } { L.LastName }");
}
//Prepare task
Task<HelperLibrary.Models.GoogleBook.RootObject[] > GetBooksTask = HelperLibrary.Helpers.APIHelper.SearchBooks("Hacker");
GetBooksTask.Wait();
HelperLibrary.Models.GoogleBook.RootObject[] Books = GetBooksTask.Result;
foreach(HelperLibrary.Models.GoogleBook.RootObject P in Books)
{
BookList_list.Items.Add(P.volumeInfo.title);
}
}
API Helper task
public class APIHelper
{
private static string BaseURL = "https://www.googleapis.com/books/v1/volumes";
public static async Task<HelperLibrary.Models.GoogleBook.RootObject[] > SearchBooks(string term)
{
using (var WebClient = new HttpClient { BaseAddress = new Uri(BaseURL) })
{
var ResponseHandler = WebClient.GetAsync($"?q= { term } ");
if (ResponseHandler.Result.IsSuccessStatusCode)
{
string x = await ResponseHandler.Result.Content.ReadAsStringAsync();
Debug.WriteLine(x);
Models.GoogleBook.RootObject[] items = JsonConvert.DeserializeObject<Models.GoogleBook.RootObject[]>(await ResponseHandler.Result.Content.ReadAsStringAsync());
return items;
}
else
{
return null;
}
}
}
}
Full error:
JsonSerializationException: Cannot deserialize the current JSON object
(e.g. {"name":"value"}) into type
'System.Collections.Generic.List`1[HelperLibrary.Models.GoogleBook+RootObject]'
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) 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 'kind', line 2, position 8.
I'm already trying to declare it to an array, not a List?
Been trough most other threads about this, can't seem to find a situation similar to mine.
You seem to have misunderstood what is the RootObject. What you have defined as such is actually the inner object inside your RootObject.
I suggest you do this;
1) Rename your RootObject to Item
public class Item
{
public string kind { get; set; }
public string id { get; set; }
public string etag { get; set; }
public string selfLink { get; set; }
public VolumeInfo volumeInfo { get; set; }
public LayerInfo layerInfo { get; set; }
public SaleInfo saleInfo { get; set; }
public AccessInfo accessInfo { get; set; }
}
2) Create a new RootObject
public class RootObject
{
public string kind { get; set; }
public int totalItems { get; set; }
public List<Item> items { get; set; }
}
Then your Deserialize should look like this;
Models.GoogleBook.RootObject root =
JsonConvert.DeserializeObject<Models.GoogleBook.RootObject>(await ResponseHandler.Result.Content.ReadAsStringAsync());
Checking the structure of the json, i think what you are trying to get is the item array of the json if i am not mistaken. What you can do is Try to create a parent class containing the array Root Object something like this:
Public class RootParent
{
public string kind {get; set;}
public int totalItems {get;set;}
public List<RootObject> items {get; set;}
}
I store the items displayed on my homepage as an XML string (in the settings).
<?xml version=""1.0""?>
<HomePageItemList>
<PlantHomePageItem>
<Name>Plant1</Name>
</PlantHomePageItem>
<PlantHomePageItem>
<Name>Plant2</Name>
</PlantHomePageItem>
<AdminHomePageItem>
<Name>Admin1</Name>
</AdminHomePageItem>
</HomePageItemList>
Some items represent a plant PlantHomePageItem, others an admin tool AdminHomePageItem. Both inherit the same base class HomePageItem
[XmlRoot("HomePageItemList")]
public class TestSerialization
{
[XmlArray("HomePageItemList")]
[XmlArrayItem("PlantHomePageItem", Type = typeof(PlantHomePageItem))]
[XmlArrayItem("AdminHomePageItem", Type = typeof(AdminHomePageItem))]
public List<HomePageItem> HomePageItemList { get; set; }
}
[XmlInclude(typeof(PlantHomePageItem))]
[XmlInclude(typeof(AdminHomePageItem))]
public class HomePageItem
{
[XmlElement("Name")]
public string Name { get; set; }
}
public class PlantHomePageItem : HomePageItem { }
public class AdminHomePageItem : HomePageItem { }
When I try an deserialize it, I have no runtime error, just an empty object...
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(XML));
XmlSerializer xs = new XmlSerializer(typeof(TestSerialization));
TestSerialization obj = (TestSerialization)xs.Deserialize(ms);
Console.WriteLine(obj.HomePageItemList.Count);
foreach (var item in obj.HomePageItemList)
{
Console.WriteLine("{0}: {1}", item.GetType().Name, item.Name);
}
returns
0
A .NET Fiddle with the entire thing is available: https://dotnetfiddle.net/f51b0K
Change your TestSerialization class to this...
[XmlRoot("HomePageItemList")]
public class TestSerialization
{
[XmlElement("PlantHomePageItem", Type = typeof(PlantHomePageItem))]
[XmlElement("AdminHomePageItem", Type = typeof(AdminHomePageItem))]
public List<HomePageItem> HomePageItemList { get; set; }
}
Your modified example...
I am querying Firebase and retrieve a collection of objects like so:
{"-K5f0ccEKkVkxTAavQKY": {
"Appeal": {
"ID": "1450273330435",
"comps": [
162248,
162272,
162273,
162281,
162544
],
"property": {
"Address": "15 Main Street",
"propID": 169729
},
"timeDateStamp": "Wed Dec 16 2015 08:42:10 GMT-0500 (Eastern Standard Time)",
"userUUID": "google:229139952703238437512",
"year": 2016
}
}}
I would like to deserialize them into objects with this definition:
public class Appeal
{
public string ID;
public List<string> comps;
public AppealProperty property;
public string timeDateStamp;
public string UUID;
public int year;
}
public class AppealProperty
{
public string address;
public string propID;
}
I have troubles getting it deserialized. I don't need the initial string (e.g. "K5f0ccEKkVkxTAavQKY"). I'm able to change the object definitions if need be. I have a feeling a Dictionary would be useful.
The quick and dirty object is to use Dictionary<string,Appeal> as your deserialization target. At that point it would be as simple as:
var firebaseLookup = JsonConvert.DeserializeObject<Dictionary<string,Appeal>>(json);
var data = firebaseLookup.Values.ToList(); // or FirstOrDefault();
This approach would also handle the case if you ever had to get multiple objects at once, and it would give you the opportunity to use that key if it turns out the key was important after all.
You could serialise your data into the classes below.
public class AppealProperty
{
public string Address { get; set; }
public int propID { get; set; }
}
public class Appeal
{
public string ID { get; set; }
public List<int> comps { get; set; }
public AppealProperty property { get; set; }
public string timeDateStamp { get; set; }
public string userUUID { get; set; }
public int year { get; set; }
}
public class FireBase
{
public Appeal Appeal { get; set; }
}
public class RootObject
{
[JsonProperty(PropertyName = " - K5f0ccEKkVkxTAavQKY")]
public FireBase FireBaseRoot
{
get;
set;
}
}
Assuming that you are using JSON.NET, you can then get the object you are after, using this snippet:
var firebaseObject = JsonConvert.DeserializeObject<RootObject>(json);
var data = firebaseObject.FireBaseRoot.Appeal;
If the root name is dynamic, as indicated by your comment, you could skip the root instead and serialise straight into the FireBase class:
JObject parsedJson = JObject.Parse(json);
var fireBase = parsedJson.First.Children().First().ToObject(typeof (FireBase));
Since I've never been able to parse a DataSnapshot with newtonSoft Json parser, I did this to build a list of object I needed to put in a ListView:
MyModelObject class
public class MyModelObject: Java.Lang.Object
{
public string Title { get; set; }
public string Description { get; set; }
public MyModelObject(){}
}
into My Listener
public void OnDataChange(DataSnapshot snapshot)
{
List<MyModelObjecct> myList = new List<MyModelObject>();
myList = databaseService
.GetMyModelObjectList(snapshot
.Children?
.ToEnumerable<DataSnapshot>());
}
Method into the DatabaseService class
public List<MyModelObject> GetMyModelObjectList(IEnumerable<DataSnapshot> enumerableSnapshot)
{
List<MyModelObject> list = new List<MyModelObject>();
foreach (var item in enumerableSnapshot)
{
list.Add(ObjectExtensions.DataSnapshotToObject<MyModelObject>(item.Children?.ToEnumerable<DataSnapshot>()));
}
return list;
}
ObjectExtensions class
public static class ObjectExtensions
{
public static T DataSnapshotToObject<T>(IEnumerable<DataSnapshot> source)
where T : class, new()
{
var someObject = new T();
var someObjectType = someObject.GetType();
foreach (var item in source)
{
someObjectType
.GetProperty(item.Key)
.SetValue(someObject, item.Value.ToString(), null);
}
return someObject;
}
}