This question is related, but IMHO not identical to
How do I serialize a C# anonymous type to a JSON string?
Serialize C# Enum Definition to Json
Whilst testing, I've also stumbled across this culprit LinqPad which made my life difficult:
Why does LINQPad dump enum integer values as strings?
Now, my actual question:
My application (in particular SyncFusion component datasources, such as MultiSelect) requires enumerations in JSON format, e.g. something like this:
[ {"Id":0,"Name":"Unknown"},{"Id":1,"Name":"Open"},{"Id":2,"Name":"Closed"},{"Id":3,"Name":"Approve"} ]
UPDATE
As dbc pointed out, my question may not have been clear enough. I do not want to serialize one entry of the enumeration, but the whole struct. The JSON could then be used for a data source in Javascript, e.g. for a , simplified:
<option value=0>Unknown</option>
<option value=1>Open</option> etc
The JSON object is identical to an Enum in a namespace (with the exception that I have given the a property name to the Key and Value of each entry:
public enum ListOptions
{
Unknown = 0,
Open = 1,
Closed = 2,
Approve = 3
}
I've struggled with Enums, all the other approaches such as specifying a Json StringConverter etc did't yield all options in an array, so I ended up using Linq. My View Model now has a string property like this:
public string CrewListOption => JsonConvert.SerializeObject(Enum.GetValues(typeof(ListOptions))
.Cast<int>()
.Select(e => new { Id = (int) e, Name = typeof(ListOptions).GetEnumName(e) }));
Given that I'm pretty much a beginner with ASP.Net Core, I find it hard to believe that this should be a good solution. Yet I find it hard to find straight-forward better examples of the same thing.
I'd appreciate it if you might be able to help me improve this, and make it potentially more generically useful to "export" whole enumerations to JSON.
Here's the full LinqPad (where Newtonsoft.Json is imported from GAC):
void Main()
{
Enum.GetValues(typeof(ListOptions)).Cast<int>().Select(e => new { Id = e, Name = (ListOptions) e } ).Dump(); // these are identical, except for the typeof()
Enum.GetValues(typeof(ListOptions)).Cast<int>().Select(e => new { Id = (int) e, Name = typeof(ListOptions).GetEnumName(e) }).Dump(); // is typeof(MyEnumType) better?
string JsonString = JsonConvert.SerializeObject(Enum.GetValues(typeof(ListOptions)).Cast<int>().Select(e => new { Id = (int) e, Name = typeof(ListOptions).GetEnumName(e) }));
JsonString.Dump(); // [{"Id":0,"Name":"Unknown"},{"Id":1,"Name":"Open"},{"Id":2,"Name":"Closed"},{"Id":3,"Name":"Approve"}]
}
public enum ListOptions {
Unknown = 0,
Open = 1,
Closed = 2,
Approve = 3
};
You may have static method like
public static EnumToDictionary<string, string> EnumToDictionary<T>() where T: Enum
{
var res = Enum.GetValues(typeof(T)).Cast<T>()
.ToDictionary(e => Convert.ToInt32(e).ToString(), e => e.ToString());
return res;
}
then for Serializing as object
var enumValues= EnumToDictionary<ListOptions>();
var result = JsonConvert.SerializeObject(enumValues);
for serializing as array
var enumValues= EnumToDictionary<ListOptions>().ToArray();
var result = JsonConvert.SerializeObject(enumValues);
Here is an example from Microsoft Docs that convert Enum to Dictionary
https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/constraints-on-type-parameters#enum-constraints
Then you can serialize the dictionary to JSON.
Related
Currently I am receiving an array of objects from a database.
object [] sqlResultData = DatabaseCall.Result();
This array of objects needs to be matched to class variables like this
CClassOfVars classVar = new CClassOfVars();
classVar.myProperty = sqlResultData[0];
classVar.myProperty1 = sqlResultData[1];
What i wish to do is pass the list of propertys on the class in order to a function and have the mapping from the object array occur automatically based on the order.
For example:
Method defined like this
FillData(object [] databaseValues, IList<object>())
Called like this
CClassOfVars classVar = new CClassOfVars();
object [] sqlResultData = DatabaseCall.Result();
FillData(sqlResultData, new List<object>(){classVar.myProperty,classVar.myProperty1});
The FillData function would hopefully type cast and set the values of myProperty and myProperty1 to the values in array locations of 0,1 etc...
Something like this
FillData(object [] databaseValues, IList<object> mapMe)
{
for (int i = 0; i < mapMe.Count; i++)
{
mapMe[i] = CastToTheCorrectType(mapMe[i], databaseValues[i]);
}
}
Cast to the correct type could look like this?? I took from here: cast object with a Type variable
public T CastToTheCorrectType<T>(T hackToInferNeededType, object givenObject) where T : class
{
return givenObject as T;
}
How can i pass a list of different object types to all have there values modified and assigned within a different function?
The matter you asking about is dark and difficult to be implemented through just a function. There are frameworks out there dealing with object relational mapping. If it is an option, install and learn some OR/M. If not ... well, there might be some dirty way.
You can use the JSON.NET library to do the heavy lifting for you. It's super easy to use and install through Nuget. My point is as follows.
Construct an anonymous object. Use the property names of the original object.
Fill it with the data from the object array. Spin a loop over the object array...
Serialize the anonymous object.
Deserialize the JSON string into the target type.
At this point, JSON.NET will handle property mapping for you.
List item
E.g. if your target type is Person you might do this:
var x = new
{
FirstName = String.Empty,
LastName = String.Empty
};
var persons = new List<Person>(sqlResultData.Length);
foreach (var record in sqlResultData)
{
x.FirstName = record[0];
x.LastName = record[1];
var s = JsonConvert.SerializeObject(x)`
var personX = JsonConvert.Deserialize<Person>(s);
persons.Add(person);
}
It looks like I have a problem with the symbols encodings between string built by my program and string retrieved from another datasource.
Here is a .NET Fiddle and here is the explanation:
var context = new List<Foo>
{
new Foo { Name = "SoW.Probing.4GEPCCore.CaptSite[1].S1U" },
new Foo { Name = "SoW.Probing.4GEPCCore.CaptSite[2].S1U" },
new Foo { Name = "SoW.Probing.2G3GPSCore.CaptSite[1].GnGpU" },
new Foo { Name = "SoW.Probing.2G3GPSCore.CaptSite[2].GnGpU" }
};
var nameToCheckPresence = GetStringFromAnotherDataSource(); // the value of the string is for example: "SoW.Probing.4GEPCCore.CaptSite.S1U"
nameToCheckPresence = nameToCheckPresence.Replace("CaptSite", "CaptSite[1]");
var foo = context.FirstOrDefault(f => f.Name == nameToCheckPresence); // Should return an object since one object does have that name
My problem is that foo is null. It works if I use this code line:
var foo = context .FirstOrDefault(f => CultureInfo.CurrentCulture.CompareInfo.Compare(f.Name, nameToCheckPresence , CompareOptions.IgnoreSymbols) == 0);
So clearly, I have a problem with symbols encoding (the .? the [ ]?). My true problem is that later, I am doing the same thing with a dictionary. The hashcode of the strings are different and the dictionary lookup also failed:
var dictionary = context.ToDictionary(f => f.Name);
var foo = dictionary[nameToCheckPresence]; // Should return the object but failed and throw a KeyNotFoundException
Is there a way to change the string symbols encoding in a global manner in the application? (WPF application in my case)
As the context can be very large, it is planed to use a Dictionary also in the first place. So if you provide me a solution that only works with Dictionary, it is not a problem.
Just for the record, the datasource is a SQLite database in which is a copy of the data of a MySQL database filled by another WPF application (running on the same computer, no specific culture setup). Finally, the nameToCheckPresence is extracted from a larger string by ANTLR4CS.
This is not a satisfactory answer, but that's all I find to solve the problem. Instead of looking into the dictionary through the indexor, I am doing a linq query:
dictionary.FirstOrDefault(pair => CultureInfo.CurrentCulture.CompareInfo.Compare(pair.Key, localFactName, CompareOptions.IgnoreSymbols) == 0).Value;
But doing this, I lost all the benefit of the dictionary access complexity. If anyone has a better solution, I will take it!
I work with an api, that returns a json formatted resultset of a database query.
I have an equivalent object or "model" for the results.
What is the best way to convert the json string into a list of this object?
Of course there are many threads about this, but no one fits my needs properly.
One of the solutions I've found was this:
var jobj = (JObject)JsonConvert.DeserializeObject(json);
var items = jobj.Children()
.Cast<JProperty>()
.Select(j => new
{
ID = j.Name,
Topic = (string)j.Value["Topic_ID"],
Moved = (string)j.Value["Moved_ID"],
Subject = (string)j.Value["subject"],
})
.ToList();
This seems pretty close to what I need. I need to be able to map the keys/values to the appropriate object attributes, which DOES already exist. So maybe you only need to change a few things to make it work for my object?
PS: I'm using Newtonsoft. Any solution for .NET or Newtonsoft or if needed any other library would be great!
I have recently been consuming data from a WebApi and i have been using the following code to convert the json object to an object to work with:
using (var client = new HttpClient())
{
var response = client.GetAsync(apiUri).Result;
// For single objects.
MyObject data = response.Content.ReadAsAsync<MyObject>().Result;
// For an array of objects
IEnumerable<MyObject> data = response.Content.ReadAsAsync<IEnumerable<MyObject>>().Result;
}
Hope this helps.
OK, so you have something like this:
public class MyObject
{
public int ID {get; set;}
public string Topic {get; set;}
public string Subject {get; set;}
}
And you want to instantiate an array of MyObjects with the properties coming from your JSON?
In that case you're just a bout there - you're currently creating a dynamic object with the same properties as MyObject, right? So all you need to do is create an actual MyObject instead:
.Select(j => new **MyObject()**
{
ID = j.Name,
Topic = (string)j.Value["Topic_ID"],
Moved = (string)j.Value["Moved_ID"],
Subject = (string)j.Value["subject"]
})
Note that if your json property names exactly match your C# ones (including case), you can do this as a one-liner with NewtonSoft: http://www.newtonsoft.com/json/help/html/SerializingJSON.htm. But to use that method you'd have to have an intermediate C# class to match your JSON, and then automap (or manually convert) those to MyObjects. Or you'd have to make sure your json and c# properties match exactly. But you're already very close to a quicker (though some would argue less elegant) solution.
Why aren't you deserializing the json into the object type directly? you can do it like this...
var obj = (YourType)JsonConvert.DeserializeObject(
json,
typeof(YourType),
new JsonSerializerSettings()
{
TypeNameHandling = TypeNameHandling.Auto,
MissingMemberHandling=MissingMemberHandling.Ignore
});
or am I missing something in the question?
I don't think the title of this post explains what the problem is, but I didn't know how to word it.
Basically I have this response from an API of which I have no control over:
"variations":{
"1033308042319364133":{
"id":"1033308042319364133",
"order":null,
"created_at":"2015-07-20 13:45:45",
"updated_at":"2015-07-20 13:47:11",
"title":"Male",
"mod_price":"+0.00",
"modifier":1033306667720114205,
"product":0,
"difference":"+£0.00"
},
"1033308953984892967":{
"id":"1033308953984892967",
"order":null,
"created_at":"2015-07-20 13:47:34",
"updated_at":"2015-07-20 13:47:34",
"title":"Female",
"mod_price":"+0.00",
"modifier":1033306667720114205,
"product":0,
"difference":"+£0.00"
},
"1033309404260204585":{
"id":"1033309404260204585",
"order":null,
"created_at":"2015-07-20 13:48:27",
"updated_at":"2015-07-20 13:48:27",
"title":"Male (Junior)",
"mod_price":"+0.00",
"modifier":1033306667720114205,
"product":0,
"difference":"+£0.00"
},
"1033309540147265579":{
"id":"1033309540147265579",
"order":null,
"created_at":"2015-07-20 13:48:44",
"updated_at":"2015-07-20 13:48:44",
"title":"Female (Junior)",
"mod_price":"+0.00",
"modifier":1033306667720114205,
"product":0,
"difference":"+£0.00"
}
}
in my c# code I loop through variations like this:
// Get our child variants
var variations = model["variations"];
var IsNull = IsJTokenNull(variations);
var variants = !IsNull ? new List<VariationResponseModel>() : null;
// If we have some variations
if (!IsNull)
{
// Loop through our variations
foreach (var variant in variations)
{
// Add our variant to our list
variants.Add(CreateVariants(variant.First));
}
}
As you can see, I am using variant.First to select the object within the property. My question is, is this the best way to do this? It seems like an awful hack.
This looks like a .net Dictionary more than a list. If VariationResponseModel has the correct properties, you could just do:
var variants = JsonConvert.DeserializeObject<Dictionary<string, Variant>>(variations);
or using the JObject class
var variants = JObject.Parse(variations).ToObject<Dictionary<string, Variant>>();
Both approaches are equivalent, and assume that you got your input as a JSON string. If your input is already a JObject, you can just use:
var variants = variations.ToObject<Dictionary<string, Variant>>()
If you need the variants in a list/enumerable afterwards, just use variants.Values
(JsonConvert / JObject is from the Json.net deserializer)
I have 5 different classes that all inherit from BaseEntity. I would like to create a new model class that will store information needed about one of these 5 classes as well as other identifiers.
When I retrieve the data for this new model from the database, all I get is a string with the class type along with an integer that represents which entry I can reference from the database.
For example, if I retrieve Id = 2, Type = "BaseBall". That means I will have need to use my BaseBallService to fetch the entry where Id == 2. If it happens to be Id = 2, Type = "BasketBall", then I will use BasketBallService.
Currently the only solution I can think of is it to have a bunch of if statements that evaluate the 'type' string. Depending on if the type matches a valid type (BaseBall, FootBall, BasketBall, etc.) then that object is returned.
Is there a way to easily do this without the need to define all 5 types in the model definition and stringing if or statements to identify this?
I hope I have identified the problem clearly enough. Let me know if any additional information is needed. I haven't written any code for this yet. I am merely trying to analyze the problem and form a solution.
I would just add a global enum at the project or solution level to store types. That way if you wish to add to it later you may without breaking any existing code as it is detached. But this may keep it well typed and thus demand a type that is listed from the end user or application. I did a simple console app to show this. You may apply the enum to any class not just a generic though. I also implement a return method to narrow down the return lists to show how I can get lists of my lists easier.
public enum types
{
Type1,
Type2,
Type3
}
public class GenericListing
{
public string Description { get; set; }
public types Type { get; set; }
}
class Program
{
public static List<GenericListing> GetTypeListing(List<GenericListing> aListings, types aTypes)
{
return aListings.Where(x => x.Type == aTypes).ToList();
}
static void Main(string[] args)
{
var stuff = new List<GenericListing>
{
new GenericListing {Description = "I am number 1", Type = types.Type1},
new GenericListing {Description = "I am number 2", Type = types.Type2},
new GenericListing {Description = "I am number 3", Type = types.Type3},
new GenericListing {Description = "I am number 1 again", Type = types.Type1},
};
string s = "";
GetTypeListing(stuff, types.Type1) // Get a specific type but require a well typed input.
.ForEach(n => s += n.Description + "\tType: " + n.Type + Environment.NewLine);
Console.WriteLine(s);
Console.ReadLine();
}
}
You may try using Dictionary, e.g.
Dictionary<String, BaseEntry> types = new Dictionary<String, BaseEntry>() {
{"BaseBall", new BaseBallService()},
{"BasketBall", new BasketBallService()},
...
}
...
var value = types["BaseBall"].GetId(2);