I have this JToken
var pv = JToken.Parse(keys["parameterValues"].ToString()).ToList()[0];
Which returns this value
{"DE:Actual Savings": 42217.0}
I can't use .Value because the float is represented as an object {42217.0}
How can I get this number? Right now I am using .ToString() and converting it
To convert the value to a defined type you could use one of the defined methods below:
System.Convert.ChangeType(jtoken.ToString(), targetType);
or
JsonConvert.DeserializeObject(jtoken.ToString(), targetType);
Let's take into consideration our sample:
string json = #{"DE:Actual Savings": 42217.0}
You could do something like:
var obj = (JObject)JsonConvert.DeserializeObject(json);
Type type = typeof(float);
var i1 = System.Convert.ChangeType(obj["DE:Actual Savings"].ToString(), type);
Hope this solves your problem.
Related
I have a json return result like the following:
Json =
{
"Id":"12345",
"FirstName":"Bob",
"LastName":"Builder",
"Links":[]
}
Links can have a list of objects of type LinkService, i want to cast even if the array is empty , so in c# i get an empty array.
I do the following
var token = JObject.Parse(Json);
var Id = token.Value<string>("Id");
var fname = token.Value<string>("FirstName");
var lbname = token.Value<bool>("LastName");
var links = JsonSerializer.Deserialize<List<LinkService>>(token.Value<Array>("Links"));
Issue is that it says cant convert System.Array to Newtonsoft.Json.JsonReader
You can convert the jToken to an object using the ToObject method:
var links = token["Links"].TObject<List<LinkService>>();
I have some methods that execute arbitrary SQL against a database and serialize that data collection into a list of a concrete type. That data is then serialized into JSON and stored in a cell in a table. Later, I need to come back and deserialize that data back into its original collection so that it can be used.
I'm having some issues figuring out how to take a Type object and create a collection of that type in order to deserialize it. Here is how my code operates:
public async Task ExecuteWidget(Guid runGuid, string widgetName, Type type, string sql,
IEnumerable<SqlParameter> parameters)
{
var report = operationsContext.ReportRuns.FirstOrDefault(n => n.RunGuid == runGuid);
CheckReportStatus(report);
var param = parameters.ToList();
var result = edwContext.Database.SqlQuery(type, sql, param.ToArray<object>());
var query = result.GetQuery(param);
var data = await result.ToListAsync();
var widgetData = new ReportRunWidgetData()
{
ReportRunId = report?.ReportRunId ?? -1, // This should never be null.
WidgetName = widgetName,
WidgetData = new JavaScriptSerializer().Serialize(data),
Query = query
};
operationsContext.ReportRunWidgetDatas.Add(widgetData);
await operationsContext.SaveChangesAsync();
}
My fetching logic looks something like this:
public object FetchWidgetData(Guid runGuid, string widgetName, Type dataType)
{
var data = operationsContext.ReportRuns
.Include("ReportRunWidgetDatas")
.FirstOrDefault(n => n.RunGuid == runGuid)?
.ReportRunWidgetDatas.FirstOrDefault(n => n.WidgetName == widgetName)?
.WidgetData;
if (data == null) return null;
var deserialized = new JavaScriptSerializer().Deserialize(data, dataType);
return deserialized;
}
Now when the ExecuteWidget method is called, the type parameter is populated by the widget's DTO datatype. For example HeadlineWidgetDTO. However, the execute command gets the data back as a List<HeadlineWidgetDTO>. When my FetchWidgetData method is called, the dataType supplied is still HeadlineWidgetDTO, but it actually needs to be of type IEnumerable<HeadlineWidgetDTO> to deserialize properly.
Given just the type for an individual data row, how can I create a Type object that is instead a collection of that type?
This is mostly a duplicate of How to use Activator to create an instance of a generic Type and casting it back to that type?, however it's hard to tell.
Basically, if you have a type object Type theType, you need to do something like:
var listType = typeof(List<>);
var typeParams = new [] {theType};
var listOfTType = listType.MakeGenericType(typeParams);
var newListOfT = Activator.CreateInstance(listOfTType);
At that point, you have a variable of type object, but that references an object of type List<WhateverYourTypeIs>. Say, theType is typeof(int), then you will have an object of List<int>. Casting it to something usuable is a whole other question though. If you want to add something to that list, I suspect the best way would be to get a MethodInfo for the Add method and Invoke it.
I thought of another way to do this if the type has a default constructor and isn't too expensive to create. Here's a sample (creating a List<int> - but that's just the way I have it coded):
var type = typeof(int);
var dummy = Activator.CreateInstance(type);
var listOfType = new[] {dummy}.ToList();
When you are finished, the listOfType variable is typed as a List<object> but refers to a List<int>. It's mostly mostly workable - for example, you can call Add(object someObj) on it. You won't get compile type parameter type checking, but you will be able to use it.
I have created a list of types like this:
var executingAssembly = Assembly.GetExecutingAssembly();
var referencedAssemblies = executingAssembly.GetReferencedAssemblies();
var assembly = referencedAssemblies.Single(x => x.Name.Equals("X.Y.Z"));
var messagesAssembly = Assembly.Load(assembly);
var types = messagesAssembly.GetTypes();
var selectedTypes = from t in types
where t.Namespace.Contains("X.Y.Z.K")
select t;
and I need to convert some json data into one of these types. How do I figure out which one is the correct one?
I have tried the following:
var jsonData = File.ReadAllText(filePair.FullPath);
foreach(var type in selectedTypes)
{
var correctObject = JsonConvert.DeserializeObject(jsonData, type);
}
Which just converts it to the first type in the list
I have also tried with the template method
var jsonData = File.ReadAllText(filePair.FullPath);
foreach(var type in selectedTypes)
{
var correctObject = JsonConvert.DeserializeObject<type>(jsonData);
}
Which "Cannot resolve symbol 'type'.
Is it possible to convert it to a the correct type in selectedTypes?
I ended up using ".NET's fastest JSOn Serializer by ServiceStack".
It has a method ServiceStack.Text.JsonSerializer.DeserializeFromString(string value, Type type) which worked perfectly.
string result ="{"AppointmentID":463236,"Message":"Successfully Appointment Booked","Success":true,"MessageCode":200,"isError":false,"Exception":null,"ReturnedValue":null}"
dynamic d = JsonConvert.DeserializeObject<dynamic>(result);
d.GetType () is Newtonsoft.Json.Linq.JObject
so how to deserialize it to dynamic object instead of JObject
It's not quite clear what is not working for you and why you care about the return type but you could directly access the properties of the deserialized object like this:
string result = #"{""AppointmentID"":463236,""Message"":""Successfully Appointment Booked"",""Success"":true,""MessageCode"":200,""isError"":false,""Exception"":null,""ReturnedValue"":null}";
dynamic d = JsonConvert.DeserializeObject<dynamic>(result);
string message = d.Message;
int code = d.MessageCode;
...
You probably want something like
var values = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(json);
This might also suit your needs (untested)
dynamic d = JsonConvert.DeserializeObject<ExpandoObject>(json);
So the problem is
I have the following line wehre value is a string
var filterValue = Expression.Constant(value, property.Type);
if property.Type is a string everything is fine however the type really could be anything, like a decimal?
I dont know how to make this work for all different types
I have this function
private static T Parse (string value)
{
return (T)TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(value);
}
using that I can do this:
var newValue = Parse(value);
var filterValue = Expression.Constant(newValue, property.Type);
however I would have to know in advance the type , I tried
var newValue = Parse(value);
but that doesnt work
Any ideas?
You don't need to know the type at all:
object value = TypeDescriptor.GetConverter(property.Type).ConvertFromString(value);
var filterValue = Expression.Constant(value, property.Type);
The generics approach isn't appropriate (or needed) in this case.
You might want special handling for null, though - or simply not allow it (property.Type) could be int? etc...