DESerialize JSON to c# objects dynamically - c#

I am getting JSON data from a webservice. it is providing me with FORM DATA with different questions and answers. every answer is a different c# object. I am trying to find the best way to map the ANSWERS to correct c# object.
for example if Question Id is "37" Then its a Address Object.
I have JSON String like in this format below
"answers": {
"37": {
"name": "yourAddress37",
"order": "6",
"sublabels": "{\"cc_firstName\":\"First Name\",\"cc_lastName\":\"Last Name\",\"cc_number\":\"Credit Card Number\",\"cc_ccv\":\"Security Code\",\"cc_exp_month\":\"Expiration Month\",\"cc_exp_year\":\"Expiration Year\",\"addr_line1\":\"Street Address\",\"addr_line2\":\"Street Address Line 2\",\"city\":\"City\",\"state\":\"State \\/ Province\",\"postal\":\"Postal \\/ Zip Code\",\"country\":\"Country\"}",
"text": "Your Home Address:",
"type": "control_address",
"answer": {
"addr_line1": "148 east 38st ",
"addr_line2": "",
"city": "Brooklyn ",
"state": "Ny",
"postal": "11203",
"country": ""
},
"prettyFormat": "Street Address: 148 east 38st <br>City: Brooklyn <br>State / Province: Ny<br>Postal / Zip Code: 11203<br>"
},
"38": {
"name": "emergencyContact",
"order": "9",
"sublabels": "{\"prefix\":\"Prefix\",\"first\":\"First Name\",\"middle\":\"Middle Name\",\"last\":\"Last Name\",\"suffix\":\"Suffix\"}",
"text": "Emergency Contact Name:",
"type": "control_fullname",
"answer": {
"first": "Pauline ",
"last": "Sandy "
},
"prettyFormat": "Pauline Sandy "
}
}
and it MAPS to following c# property
public Dictionary<int, answer> answers{ get; set; }
Then I have a generic Answer class
public class answer
{
public string name { get; set; }
public dynamic answer { get; set; }
}
if you look at the ANSWER data from json then you will see its different for every question. for example one answer would be ADDRESS OBJECT, other answer would be FIRST & LAST NAME object.
my question is, how can i deserialize json into correct objects/properties automatically? I can create different POCO objects, such as address & ProfileName, but how would i map them automatically to correct object/property.
EDIT:
Loop through all Answers
foreach (var a in item.answers)
{
// pass the ANSWER OBJECT (dynamic data type) to function
createNewApplication(System.Convert.ToInt16(a.Key), a.Value.answer,ref app);
}
private void createNewApplication(int key, dynamic value,ref HcsApplicant app)
{
if (key == 4) // data is plain string
app.yourPhone = value;
if (key == 8)
app.yourEmail = value;
if (key==37) // data is a object
app.address = value.ToObject<address>();
}
is this approach OK? any cleaner way of doing it?

I personally don't like every option that involves custom parsing and looking directly on the questions.
You can make use of partial deserialization via JToken class.
Just declare your answers dictionary as such:
public Dictionary<int, JToken> Answers{ get; set; }
And then whenever you need the address page you can simply do Answers[37].ToObject<Address>(). How you manage to call this method, depends upon the rest of your code, but you can embed it in properties, in a big switch, in multiple methods, one for each class. One option I like is to have a static From method in each deserializable class:
public class Address
{
public string Name { get; set; }
// all the othe properties
// ....
public static Address From(Dictionary<int, JToken> answers)
{
return answers?.TryGetValue(37, out var address) ?? false
? address?.ToObject<Address>()
: null;
}
}
// so you can just write:
var address = Address.From(answers);
As a side note, remember that the default deserialization settings for Json.Net are case insensitive, so you can deserialize the name property from JSON to a more idiomatic Name property on your POCOs.

Make a constructor for each answer type that constructs by parsing a JSON object string. Make all the answers implement an interface, e.g. IAnswer. Map all constructors (as functions) to the corresponding question IDs in a dictionary. Lastly, loop through the questions, call each constructor, and maybe put them in a new dictionary.
Example code:
interface IAnswer { };
public class ExampleAnswer : IAnswer
{
public ExampleAnswer(String JSONObject)
{
// Parse JSON here
}
}
delegate IAnswer AnswerConstructor(String JSONObject);
Dictionary<int, AnswerConstructor> Constructors = new Dictionary<int, AnswerConstructor>()
{
{1234, ((AnswerConstructor)(json => new ExampleAnswer(json)))}
// Add all answer types here
};
Dictionary<int, IAnswer> ParseAnswers(Dictionary<int, String> JSONObjects)
{
var result = new Dictionary<int, IAnswer>();
foreach (var pair in JSONObjects)
result.Add(pair.Key, Constructors[pair.Key](pair.Value));
return result;
}
Edit: Look at Matt's answer for some good options for how to parse JSON.
Edit2, In response to your edit: That looks like a good way of doing it! I think it's better than my answer, since you can keep all type information, unlike my method.
The only thing I see that you might want to change is using else if or switch instead of multiple ifs. This could increase performance if you have many answers.

You have a couple of options:
Deserialize into a dynamic object using the System.Web package as per this answer or the JSON.Net package as per this answer then use conditional checks/the null propagation operator to access a property.
Automatically deserialize down to the level where there are differences, then have code to manual deserialize the properties that are different into the correct POCO types on your parent Deserialized object.
Leverage one of the Serialization Callbacks provided by JSON.Net (OnDeserializing or OnDeserialized) to handle populating the different properties into the correct types as part of the deserialization pipeline.
With approaches 2 and 3 you could write a nicer helper method on your POCO that inspected the objects properties and returned a result which would be the type that was set (I would recommend returning an Enum) e.g.:
public PropertyTypeEnum GetPropertyType(MyPocoClass myPocoClass)
{
if (myPocoClass.PropertyOne != null)
{
return PropertyTypeEnum.TypeOne;
}
else if (...)
{
return PropertyTypeEnum.TypeN
}
else
{
// probably throw a NotImplementedException here depending on your requirements
}
}
Then in your code to use the object you can use the returned Enum to switch on the logical paths of your code.

Related

Json Serialization/Contract Resolvers - Need to serialize object so contained list of key value pairs is converted to name value pairs at same level

Since I'm having a hard time explain my question, I made a fiddle.
https://dotnetfiddle.net/aa18qT
I have a class that contains a list of another class with only two properties a key and a value. Alternatively I could use a dictionary. I am serializing this to json.
Currently I have
{
"part":1,
"quant":2,
"comments":"something",
"CustomFields": [
{
"key":"groc1",
"value":"truffles"
},
{
"key":"groc 2",
"value":"some thing"
}
]
}
And what I want is
{
"part":1,
"quant":2,
"comments":"something",
"groc 1": "truffles",
"groc 2":"some thing"
}
Where groc 1 and groc 2 are two of the key value pairs. The names (groc 1) are not known at compile time and could be anything in any amount. They need to be passed as parameters to another external system with those unknown fields as the name/key.
Trying to figure out how best to do this. I've been fiddling with contract resolvers and converters but not getting anywhere..maybe something with expando objects and reflection? But seems like someone must have run into this before so maybe there is an easier way all my googling hasn't found yet. Seems like it should be simple but I've been staring at it too long.
I can change the structure or type of the child object, but output needs to be like above.
Any suggestions?
you can try this
var newObj=JObject.Parse(json);
var customFields=(JArray) newObj["CustomFields"];
newObj.Properties().Where(p=> p.Name=="CustomFields").First().Remove();
foreach (JObject item in customFields)
newObj.Add((string) item["key"],item["value"]);
json=newObj.ToString();
json
{
"part": 1,
"quant": 2,
"comments": "something",
"groc 1": "truffles",
"groc 2": "some thing"
}
but if you need c# classes, you have to create a custom class using a Dictionary as JsonExtensionData
Item newItem=newObj.ToObject<Item>();
public class Item
{
public int part { get; set; }
public int quant { get; set; }
public string comments { get; set; }
[JsonExtensionData]
public IDictionary<string, object> CustomFields { get; set; }
}

JSON Newtonsoft C# Good Practice for Serialize/ Deserialize Lists of Objects

I've readed others posts here about this question
Serializing a list of Object using Json.NET
Serializing a list to JSON
Merge two objects during serialization using json.net?
All very useful. Certain, I can serialize in one json two lists, but I cant deserialize it.
I´m working with Json Newtonsoft, C#, MVC5, framework 4.5. This is the scenario:
C# CODE
public class User
{
public int id { get; set; }
public string name { get; set; }
}
public class Request
{
public int id { get; set; }
public int idUSer{ get; set; }
}
List<User> UserList = new List<User>();
List<Request> RequestList = new List<Request>();
string json= JsonConvert.SerializeObject(new { UserList, RequestList });
JSON RESULT
{
"UserList":[
{
"id":1,
"name":"User 1"
},
{
"id":2,
"name":"User 2"
},
{
"id":3,
"name":"User 3"
}
],
"RequestList":[
{
"id":1,
"idUSer":1
},
{
"id":2,
"idUSer":1
},
{
"id":3,
"idUSer":1
},
{
"id":4,
"idUSer":2
}
]
}
C# DESERIALIZE
I dont Know how configure the settings of Json.Deserialize< ?, Settings>(json) for indicate what types of objects are being deserialized.
Change of approach
So that, change of approach, I've created a new class "Cover" in order to put the lists together and serialize one object
public class Cover
{
private List<User> user = new List<User>();
private List<Request> request = new List<Request>();
public List<User> User
{
get { return user;}
set { User = value;}
}
public List<Request> Request
{
get {return request;}
set {Request = value;}
}
}
SERIALIZE
string json = JsonConvert.SerializeObject(cover);
JSON The json result is the same.
DESERIALIZE
Cover result = JsonConvert.DeserializeObject<Cover>(json, new
JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto });
It's work fine. My situation is resolved but I have doubts about concepts, in my mind something is not clear:
MY QUESTIONS ARE:
For the first aproach:
Do you think that there is a way to deserialize a json with different lists of objects? Is not a good practice?
Second aproach: Why jsons are equals for first situation?
In JSON.NET you need to specify the type you're about to deserialize, by supplying its name as a type argument to DeserializeObject.
However, in this line:
string json= JsonConvert.SerializeObject(new { UserList, RequestList });
you create anonymous object and then serialize it - new { UserList, RequestList }. So there is the catch - you cannot use anonymous type as type arguments.
To handle such situations, JSON.NET provides DeserializeAnonymousType<>. It doesn't require you to supply the type argument; actually you can't as you going to deserialize anonymous type. Instead it is inferred from the type of the second argument, passed to the method. So you just create a dummy, anonymous object, without data and pass it to this method.
// jsonData contains previously serialized List<User> and List<Request>
void DeserializeUserAndRequest(string jsonData)
{
var deserializedLists = new {
UserList = new List<User>(),
RequestList = new List<Request>()
};
deserializedLists = JsonConvert.DeserializeAnonymousType(jsonData, deserializedLists);
// Do your stuff here by accessing
// deserializedLists.UserList and deserializedLists.RequestLists
}
Of course this all works fine, but this approach suggests that you already know the structure of the serialized data. If this structure doesn't match the structure of the initialized by you anonymous type you'll get nothing after the DeserializeAnonymousType method. And this is valid not just for the type of the properties of the anonymous type, but for their names too.
To your first question:
I would consider the option with the Cover class the 'best practice' as you are using the same model for serialization and deserialization and it's all up to Json.NET to figure out how to do the (de)serialization magic.
If for some reason you don't want to use this approach, there are two other options:
Anonymous types: http://www.newtonsoft.com/json/help/html/DeserializeAnonymousType.htm
Deserializing into a dictionary: http://www.newtonsoft.com/json/help/html/DeserializeDictionary.htm
To your second question - Are you sure the generated JSON is absolutely the same with both approaches? (You can use a tool like www.diffchecker .com to verify)
With your second approach the top-level names should be different - it should be 'Users' instead of 'UserList' and 'Requests' instead of 'RequestList'

C# deserailize json in non standard format

I am consuming a web service that will calculate tax. The problem is I don't always get the data back in exactly the same formatn (see example below). When I deserialize the data my code throws an exception. Any tips on what I can do to allow the deserialization to handle a single element or an array of a single element? FYI, I get back a lot more data in addition to the tax, but I am only showing the tax part to keep it simple.
Sometimes I get the data like this:
{
"data": {
"tax": [{
"amount": 0.00,
"category": 0.0
}]
}
}
Sometimes I get it like this:
{
"data": {
"tax": {
"amount": 336.01,
"category": 0.0
}
}
}
Here is my class:
public class Tax
{
public float amount { get; set; }
public float category{ get; set; }
}
I am thinking about adding an [XmlIgnore] attribute and manually deserailizing to get the tax data, but I would like to stay away from that if possible.
Not sure how XmlIgnore would help with your JSON serialization, but i would suggest using Newtonsoft.Json to deserialize your payload to JObject. Then you can use Linq to JSON to investigate the result and perhaps manually instantiate your own object based on the type of "tax" property (JArray or JObject)
see LINQ to JSON for more info.
Make two (or more) different classes, then use the one that doesn't throw an exception when you deseralize.
It looks like you could deseralize the array data using this class:
public class data
{
public Dictionary<string, double> tax { get; set; }
}
If that class successfully deserializes, you can then copy it over to the tax class, either manually, or by using Reflection.
I'd use JSON.Net (link to nuget). Then I'd get a JObject from JObject.Parse method and check whether the relevant child element is JObject or JArray. Then, I'd convert it to your data class (or a dynamic type)
dynamic taxData;
var json = JObject.Parse(response);
var rawTaxData = json["data"]["tax"];
if (rawTaxData is JObject)
{
taxData = JsonConvert.DeserializeObject(rawTaxData);
}
else if (rawTaxData is JArray)
{
var actualData = rawTaxData [0];
taxData = JsonConvert.DeserializeObject(actualData);
}
Also, just to be sure that your server actually returned data and not, for example, error message, use TryGetValue:
JToken dataToken;
if (!json.TryGetValue("data", out dataToken))
{
var rawTaxData = dataToken["tax"];
// ...
}

C# Parse/Deserialize JSON partially with Newtonsoft

I have to extract a part of json-string using .net or newtonsoft json.
JSON:
var json = "{\"method\":\"subtract\",\"parameters\":{\"minuend\":\"SOME_CUSTOM_JSON_OBJECT_DIFFERENT_FOR_EACH_METHOD\",\"subtrahend\":23}}";
C# Class:
class MyJson{
public string method { get; set; }
//public string parameters {get; set;}
public object parameters {get; set;}
}
I do not need to parse all the children of "parameters" json-object. "parameters" could be a very big object ([{obj1}...{obj1000}], objX of 1000 fields), parse which would be not performant.
I would like i.e. to pass it exactly as it is on some point, so conversion "string-C#object-string" would be redundant.
I do not want use Regexp or string transformations (string.Substring, Split and co), because of error margin, I know that all .net and newtonsoft string transformations based.
Question 1: if I define a property of type "object", how newtonsoft will handle this? (Documentation is worse than msdn, so I'm looking for the input from you, who already tried this).
static void Main(string[] args)
{
var json = "{\"method\":\"subtract\",\"parameters\":{\"minuend\":42,\"subtrahend\":23}}";
var data = JsonConvert.DeserializeObject<MyJson>(j);
// what internal representaion of data.parameters?
// How is it actually converted from json-string to an C# object (JObject/JsonObject).
}
In perfect case:
"parameters" is a string and calling
ExtractMyJson(jsonString)
gives me the json string of parameters.
Basically I need the newtonsoft version of
string ExtractMyJson(jsonString){
var p1 = jsonString.Split(",");
// .. varios string transformations
return pParams;
}
Note: please don't reference "dynamic" keyword or ask why no string transformations, it's the very specific question.
If you know that your parameters are unique you can do something like this:
class MyJson
{
public string method { get; set; }
public Dictionary<string,object> parameters { get; set; }
}
................
string json = "{\"method\":\"subtract\",\"parameters\":{\"minuend\":{\"img\": 3, \"real\": 4},\"subtrahend\":23}}";
var data = JsonConvert.DeserializeObject<MyJson>(json);
If you let it as object is going to receive the type Newtonsoft.Json.Linq.JObject.
Have you tried JTOKEN?
It is a rather simple solution to partially read basic or nested JSONs as described in this post.
For a nested JSON
{
"key1": {
"key11": "value11",
"key12": "value12"
}
"key2": "value2"
}
it would look like this
JToken token = JToken.Parse(json);
var value12 = token.SelectToken("key1.key12");
to get the element of the key "key12.
I think this could go nicely with your problem.
Well Objects are treated the same way your parent object is treated. It will start from the base of the graph. So if you have something like:
Person
{
Address Address {get;set;}
}
The Json will start Deserializing Address and then add in the Person object.
If you want to limit thesize of the graph depth you can use a setting like :
JsonConvert.DeserializeObject<List<IList<IList<string>>>>(json, new JsonSerializerSettings
{
MaxDepth = 2
});
For more configurations of the JsonSerializer check JsonSerializerSettings
If your field is an object then that object will have the KeyValuePair of every property that it holds, based on that when you cast that field you can access that type.(the behaviour is the same as assigning a type to an object in C#).
Update: So if you question using JsonObject or type, well JObject is and intermediary way to construct the json format in a generic format. But using the Type deserializatin means you can ignore properties you are not interested in. Mapping to a json with a type makes more sense because it creates a new object and dismisses the old JObject.

Serializing C# classes to MongoDB without using discriminators in subdocuments

I'm writing C# code that writes to a Mongo database used by an existing Web app (written in PHP), so I need to not change the existing structure of the database. The database structure looks something like this:
{
"_id": ObjectId("5572ee670e86b8ec0ed82c61")
"name": "John Q. Example",
"guid": "12345678-1234-5678-abcd-fedcba654321",
"recordIsDeleted": false,
"address":
{
"line1": "123 Main St.",
"city": "Exampleville"
}
}
I read that in to a class that looks like this:
public class Person : MongoMappedBase
{
public ObjectId Id { get; set; }
public Guid Guid { get; set; }
public bool RecordIsDeleted { get; set; }
public string Name { get; set; }
public AddressData Address { get; set; }
// etc.
}
public class AddressData : MongoMappedBase
{
public string Line1 { get; set; }
public string City { get; set; }
// etc.
}
The reading code looks like:
var collection = db.GetCollection<Person>("people");
List<Person> people = collection.Find<Person>(_ => true).ToListAsync().Result;
(Note: I'm still in development. In production, I'm going to switch to ToCursorAsync() and loop through the data one at a time, so don't worry about the fact that I'm pulling the whole list into memory.)
So far, so good.
However, when I write the data out, this is what it looks like:
{
"_id": ObjectId("5572ee670e86b8ec0ed82c61")
"name": "John Q. Example",
"guid": "12345678-1234-5678-abcd-fedcba654321",
"recordIsDeleted": false,
"address":
{
"_t": "MyApp.MyNamespace.AddressData, MyApp",
"_v":
{
"line1": "123 Main St.",
"city": "Exampleville"
}
}
}
Notice how the address field looks different. That's not what I want. I want the address data to look just like the address data input (no _t or _v fields). In other words, the part that ended up as the contents of _v is what I wanted to persist to the Mongo database as the value of the address field.
Now, if I was just consuming the Mongo database from my own C# code, this would probably be fine: if I were to deserialize this data structure, I assume (though I haven't yet verified) that Mongo would use the _t and _v fields to create instances of the right type (AddressData), and put them in the Address property of my Person instances. In which case, everything would be fine.
But I'm sharing this database with a PHP web app that is not expecting to see those _t and _v values in the address data, and won't know what to do with them. I need to tell Mongo "Please do not serialize the type of the Address property. Just assume that it's always going to be an AddressData instance, and just serialize its contents without any discriminators."
The code I'm currently using to persist the objects to Mongo looks like this:
public UpdateDefinition<TDocument> BuildUpdate<TDocument>(TDocument doc) {
var builder = Builders<TDocument>.Update;
UpdateDefinition<TDocument> update = null;
foreach (PropertyInfo prop in typeof(TDocument).GetProperties())
{
if (prop.PropertyType == typeof(MongoDB.Bson.ObjectId))
continue; // Mongo doesn't allow changing Mongo IDs
if (prop.GetValue(doc) == null)
continue; // If we didn't set a value, don't change existing one
if (update == null)
update = builder.Set(prop.Name, prop.GetValue(doc));
else
update = update.Set(prop.Name, prop.GetValue(doc));
}
return update;
}
public void WritePerson(Person person) {
var update = BuildUpdate<Person>(person);
var filter = Builders<Person>.Filter.Eq(
"guid", person.Guid.ToString()
);
var collection = db.GetCollection<Person>("people");
var updateResult = collection.FindOneAndUpdateAsync(
filter, update
).Result;
}
Somewhere in there, I need to tell Mongo "I don't care about the _t field on the Address property, and I don't even want to see it. I know what type of objects I'm persisting into this field, and they'll always be the same." But I haven't yet found anything in the Mongo documentation to tell me how to do that. Any suggestions?
I figured it out. I was indeed having the problem described at https://groups.google.com/forum/#!topic/mongodb-user/QGctV4Hbipk where Mongo expects a base type but is given a derived type. The base type Mongo was expecting, given my code above, was actually object! I discovered that builder.Set() is actually a generic method, builder.Set<TField>, which can figure out its TField type parameter from the type of its second argument (the field data). Since I was using prop.GetValue(), which returns object, Mongo was expecting an object instance on my Address field (and the other fields that I left out of the question) and therefore putting _t on all those fields.
The answer was to explicitly cast the objects being returned from prop.GetValue(), so that builder.Set() could call the correct generic method (builder.Set<AddressData>() rather than builder.Set<object>()) in this case. The following was a bit ugly (I wish there was a way to get a specific generic function overload by reflection at runtime, as I could have converted that whole switch statement to a single reflection-based method call), but it worked:
public UpdateDefinition<TDocument> BuildUpdate<TDocument>(TDocument doc) {
var builder = Builders<TDocument>.Update;
var updates = new List<UpdateDefinition<TDocument>>();
foreach (PropertyInfo prop in typeof(TDocument).GetProperties())
{
if (prop.PropertyType == typeof(MongoDB.Bson.ObjectId))
continue; // Mongo doesn't allow changing Mongo IDs
if (prop.GetValue(doc) == null)
continue; // If we didn't set a value, don't change existing one
switch (prop.PropertyType.Name) {
case "AddressData":
updates.add(builder.Set(prop.Name, (AddressData)prop.GetValue(doc)));
break;
// Etc., etc. Many other type names here
default:
updates.add(builder.Set(prop.Name, prop.GetValue(doc)));
break;
}
}
return builder.Combine(updates);
}
This resulted in the Address field, and all the other fields I was having trouble with in my real code, being persisted without any _t or _v fields, just like I wanted.
Thanks #rmunn for this question, it helped me a lot.
I was struggling with this same problem when I found this Q&A. After further digging I found that you can remove the switch statement in the accepted answer by using BsonDocumentWrapper.Create(). This is a link to where I found the tip.
Here's a example for anyone else looking:
public UpdateDefinition<TDocument> BuildUpdate<TDocument>(TDocument doc) {
var builder = Builders<TDocument>.Update;
var updates = new List<UpdateDefinition<TDocument>>();
foreach (PropertyInfo prop in typeof(TDocument).GetProperties())
{
if (prop.PropertyType == typeof(MongoDB.Bson.ObjectId))
continue; // Mongo doesn't allow changing Mongo IDs
if (prop.GetValue(doc) == null)
continue; // If we didn't set a value, don't change existing one
updates.add(builder.Set(prop.Name, BsonDocumentWrapper.Create(prop.PropertyType, prop.GetValue(doc))));
}
return builder.Combine(updates);
}
You can convert your object to JSON string and from that JSON string you can convert back to BsonArray (if list) or BsonDocument (if object)
Object that you want to update
public UpdateDefinition<T> getUpdate(T t)
{
PropertyInfo[] props = typeof(T).GetProperties();
UpdateDefinition<T> update = null;
foreach (PropertyInfo prop in props)
{
if (t.GetType().GetProperty(prop.Name).PropertyType.Name == "List`1")
{
update = Builders<T>.Update.Set(prop.Name, BsonSerializer.Deserialize<BsonArray>(JsonConvert.SerializeObject(t.GetType().GetProperty(prop.Name).GetValue(t))));
}
else if (t.GetType().GetProperty(prop.Name).PropertyType.Name == "object")
{
/* if its object */
update = Builders<T>.Update.Set(prop.Name, BsonSerializer.Deserialize<BsonDocument>(JsonConvert.SerializeObject(t.GetType().GetProperty(prop.Name).GetValue(t))));
}
else
{
/*if its primitive data type */
update = Builders<T>.Update.Set(prop.Name, t.GetType().GetProperty(prop.Name).GetValue(t));
}
}
return update;
}
This will update any type of object list, you just need to pass the object

Categories