I’ve got a very simple scenario.
I have an api response that simply returns an array of strings.
[‘test’,’test2’,’test3’]
I need to deserialise into an object to integrate with some current code.
I’ve tried using a straight class with a single property of type List but no dice.
How to deserialise into single object?
If you are using Visual Studio, you can try to use the Paste special - Paste JSON as classes under the Edit menu. Otherwise you can use this simple tool https://json2csharp.com/.
For deserialize the json string, you can use this two extension method:
using System.Runtime.Serialization.Json;
public static T DeserializeFromJsonString<T>(this string data)
{
using (MemoryStream stream = new MemoryStream(Encoding.UTF8.GetBytes(data)))
return stream.DeserializeFromJsonStream<T>();
}
public static T DeserializeFromJsonStream<T>(this Stream stream)
{
T result = (T)new DataContractJsonSerializer(typeof(T)).ReadObject(stream);
return result;
}
if you need deserialise the api outPut into single object:
class _object
{
public List<string> value { get; set; }
public _object(List<string> val)=>
value = val;
}
string[] apiOutput = { "test", "test2", "test3" };
_object myobject = new _object(apiOutput.ToList());
If you want to convert the array into a list of objects:
class _object
{
public string value { get; set; }
public _object(string val)=>
value = val;
}
string[] apiOutput = {"test", "test2", "test3"};
List<_object> listObjest = apiOutput.Select(x => new _object(x)).ToList();
listObjest.ForEach(x=>Console.WriteLine(x.value));
Related
Let's say I have a Value that is deserialized from a class.
public class MyValue
{
public string MyPropertyA { get; set; }
public string MyPropertyB { get; set; }
public string DeserializationClass { get; } = typeof(MyValue).Name;
}
I serialize this using JsonConvert class. MyValue class has a property DeserializationClass that should be used as info from which class the string was serialized from. In other words, when I deserialize the string into an object, this property serves as info which class should be used to deserialize the string. However, I am kinda stuck here as I am not sure how to get back the class from the string. Can anybody help me here?
public class Program
{
void Main()
{
var serialized = Serialize();
var obj = Deserialize(serialized);
}
string Serialize()
{
var objValue = new MyValue { MyPropertyA="Something", MyPropertyB="SomethingElse" };
return JsonConvert.SerializeObject<MyClass>(value);
}
object Deserialize(string serialized)
{
//How to deserialize based on 'DeserializationClass' property in serialized string?
return = JsonConvert.Deserialize<???>(serialized);
}
}
EDIT: Modified example to make it more clear what I need as I don't have access to objValue when I need to deserialize the string.
probably you might need to use JsonSerializerSettings.
What you might need to do is
JsonSerializerSettings setting = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.All,
};
and then while serializing use this setting.
var serialized = JsonConvert.SerializeObject(objValue,setting);
this will give you Json like this
{"$type":"WPFDatagrid.MyValue, WPFDatagrid","MyPropertyA":"Something","MyPropertyB":"SomethingElse","DeserializationClass":"MyValue"}
from this you can find the name of the class used it to actually get your type.
Hope this helps !!
There is an overload
If your Type is in form of a Namespace, you can obtain the type from a string representation:
Type objValueType = Type.GetType("Namespace.MyValue, MyAssembly");
object deserialized = JsonConvert.Deserialize(objValueType, serialized);
I am using Newtonsoft.JSON. I won't know the type of object passed to this method, or retrieved to this method, so I am attempting to use DeserializeObject on an object I do not know the type of.
Is this possible? If so, how?
Here is my code.
public static List<T> GetObject<T>(string cacheKey, IEnumerable<T> obj)
{
using (HttpClient client = new HttpClient())
{
var response = client.GetAsync("http://localhost:53805/api/NonPersisted/Get/" + cacheKey).Result;
obj = JsonConvert.DeserializeObject<obj.GetType>(response.Content.ToString());
return obj.ToList();
}
}
I attempted first to use
obj = JsonConvert.DeserializeObject<List<T>>(response.Content.ToString());
This didn't work, obviously, it was unable to parse.
Getting the Type of the object won't build, it says obj is a variable but used like a type.
EDIT
It appears you can use a generic List<T> without knowing the type with JsonConvert.DeserializeObject<> The real error was that the response.Content was only returning the type. You need to have...
obj = JsonConvert.DeserializeObject<List<T>>(response.Content.ReadAsStringAsync().Result);
You can make GetObject method generic without having parameter IEnumerable<T> obj.
Following solution I am suggesting with assumption that you know the format of the JSON value being returned from the URL.
For example, that the URL returns JSON which contains array of items and each item has two properties firstName and lastName.
var response = "[{\"firstName\":\"Melanie\",\"lastName\":\"Acevedo\"},
{\"firstName\":\"Rich\",\"lastName\":\"Garrett\"},
{\"firstName\":\"Dominguez\",\"lastName\":\"Rose\"},
{\"firstName\":\"Louisa\",\"lastName\":\"Howell\"},
{\"firstName\":\"Stone\",\"lastName\":\"Bean\"},
{\"firstName\":\"Karen\",\"lastName\":\"Buckley\"}]";
I can write GetObject method as following.
public static List<T> GetObject<T>()
{
var response = "
[{\"firstName\":\"Melanie\",\"lastName\":\"Acevedo\"},
{\"firstName\":\"Rich\",\"lastName\":\"Garrett\"},
{\"firstName\":\"Dominguez\",\"lastName\":\"Rose\"},
{\"firstName\":\"Louisa\",\"lastName\":\"Howell\"},
{\"firstName\":\"Stone\",\"lastName\":\"Bean\"},
{\"firstName\":\"Karen\",\"lastName\":\"Buckley\"}]";
var obj = JsonConvert.DeserializeObject<List<T>>(response);
return obj.ToList();
}
Here T in above method can by any type which has properties firstName and lastName. For example
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public DateTime DateOfBirth { get; set; }
}
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public double Salary { get; set; }
}
I can call GetObject method by passing either Person or Employee and get the JSON string deserialize to the collection of objects of these classes as following.
var persons = GetObject<Person>();
foreach (var item in persons)
{
Console.WriteLine($"{item.FirstName} {item.LastName}");
}
var employees = GetObject<Employee>();
foreach (var item in employees)
{
Console.WriteLine($"{item.FirstName} {item.LastName}");
}
Overall, the point I am trying to make is if format of the JSON is know the passing appropriate Type to JsonConvert.Deserialize<T> should work without any problem.
If incoming JSON represents a collection and trying to deserialize it to a simple class would fail and vice versa too will not work.
So for your problem, if you know that JSON is going to be a collection then using JsonConvert.Deserialize<List<T>> should not give you any problem as long T has the properties to which values from JSON can be set.
I hope this would help you resolve your issue.
I don't think you can call Deserialize<T>(..) if you do not known type T.
Only thing I can think of is getting Object:
public static Object GetObject(string cacheKey)
{
using (HttpClient client = new HttpClient())
{
var response = client.GetAsync("http://localhost:53805/api/NonPersisted/Get/" + cacheKey).Result;
var obj = JsonConvert.DeserializeObject(response.Content.ToString());
return obj;
}
}
I am not in a position where I can test this right now, but I think the following could work. I have found that JSON.NET does not like List<T> when deserializing, I typically get around this by using arrays instead.
static HttpClient _httpClient = new HttpClient();
public static async Task<T[]> GetObject<T>(string cacheKey)
{
HttpResponseMessage response = await _httpClient .GetAsync("http://localhost:53805/api/NonPersisted/Get/" + cacheKey);
return JsonConvert.DeserializeObject<T[]>(response.Content.ToString());
}
I took the liberty of removing the using statement for HttpClient and made it a static member instead. I also changed the method to run async, you can change it back easily but as I mentioned in my comment you might want to avoid HttpClient and use WebClient instead.
You can do this by passing the type into the function without strongly typing it.
For example:
Type type = obj.GetType();
JsonConvert.DeserializeObject(json, type);
I'm trying to cast dynamic structure which contains a decimal to a concrete class. I haven't been able to find a reasonable solution to that so I'm using "hacky" way by serializing the dynamic structure to JSON and then by deserializing it back to a concrete class. My first question is - Is there a better way to do that?
Actually I've noticed something really strange for me. After doing what I just explained I was trying to get string values out of those decimal values - a.ToString(CultureInfo.InvariantCulture);
To my surprise those strings were different! One was 10 and another 10.0. Can you explain why this happens? During debugging the valus both seem to be the same...
This is my code so you can easily check this:
using System.Globalization;
using Newtonsoft.Json;
using NUnit.Framework;
namespace SimpleFx.UnitTests.UnitTest
{
public class DecimalStruct
{
public DecimalStruct(decimal a)
{
A = a;
}
public decimal A { get; set; }
}
public class DynamicDecimalTest
{
/// <summary>
/// "Hacky" way of casting dynamic object to a concrete class
/// </summary>
public static T Convert<T>(dynamic obj) where T : class
{
var serialized = JsonConvert.SerializeObject(obj);
return JsonConvert.DeserializeObject<T>(serialized);
}
[Test]
public void CastTest()
{
decimal a = 10;
dynamic s1 = new DecimalStruct(a);
var s2 = Convert<DecimalStruct>(s1);
Assert.AreEqual(a, s1.A);
Assert.AreEqual(a, s2.A);
Assert.AreEqual(a.ToString(CultureInfo.InvariantCulture), s1.A.ToString(CultureInfo.InvariantCulture));
Assert.AreEqual(a.ToString(CultureInfo.InvariantCulture), s2.A.ToString(CultureInfo.InvariantCulture)); // this fails because "10.0" is not equal "10"
}
}
}
Please consider the following example to convert dynamic to concrete
var typeName = "YourNamespace.ExampleObj";
object obj = new
{
A = 5,
B = "xx"
};
var props = TypeDescriptor.GetProperties(obj);
Type type = Type.GetType(typeName);
ExampleObj instance = (ExampleObj)Activator.CreateInstance(type);
instance.A = (int)props["A"].GetValue(obj);
instance.B = (string)props["B"].GetValue(obj);
//serialize the instance now...
I'm trying to convert a string with JSON data to an array.
I'm using NewtonSoft.JSON
The following line of code holds my JSON data in a string:
string jsonString = manage.getData();
I've tried the following:
name[] result = JsonConvert.DeserializeObject<name[]>(jsonString);
string name = result.Name;
Name class:
using System;
namespace Zoekfunctie {
public class name {
public string Name {get;set;}
public string Id { get; set; }
}
}
So how can I convert my JSON string to an array of strings?
JSON string: [{"id":"42","naam":"Bas Jansen"},{"id":"41","naam":"Bas Jansen"}]
You just need to call DeserializeObject providing the array type instead of the single class type. Here's a short but complete program demonstrating this... I've adjusted your JSON and class to match each other.
using System;
using System.IO;
using Newtonsoft.Json;
public class Person
{
public string Id { get; set; }
public string Name {get;set;}
}
class Program
{
static void Main(string[] args)
{
string text = "[{\"id\":\"42\",\"Name\":\"Bas Jansen\"},{\"id\":\"41\",\"Name\":\"Bas Jansen\"}]";
var array = JsonConvert.DeserializeObject<Person[]>(text);
Console.WriteLine(array.Length);
Console.WriteLine(array[0].Id);
}
}
Ok, so your JSON string is already an array.
If you are looking for an Array of Name class, then this is the first thing that springs to my mind.
List<Name> result = new List<Name>();
var tempArr = JArray.Parse(jsonString);
foreach(var item in tempArr){
result.Add(new Name(){Name = item.naam})
}
You can then call result.ToArray() if you need an array and the list wont suffice.
If your name class represented the objects in your JSON fully (the ID field is missing) you could replace the line in the foreach with
result.Add(JsonConvert.Deserialize<Name>(item.ToString()));
As the to string method on a JToken (The type of elements within a JArray when it is parsed) returns the JSON string for the object.
Hope this is along the lines of what you are looking for.
Lets assume I have the following JSON Object:
{
"Key": "\"QTuY+0m31w2QiZGl4h+W8w==\"",
"Value":
[
"addgroup",
"viewgroup",
"editgroup"
]
}
How can I deserialize the Value part in a C# string[]?
The problem is, string[] is not the only type I have in the Value part, it can be everything, so I need to use dynamic.
I am using JSON.net and when I use the JsonConvert.DeserializeObject method I get a runtime binder exception.
This is the method I use to deserialize:
public async Task<Tuple<string, dynamic>> ReadCachingEntryAsync(string uri) {
var data = tools.ReadEntry(Path.Combine(cacheFolder, uri.Replace("/", "")));
var res = new Tuple<string, dynamic>(string.Empty, null);
if (data != null) {
var dat = JsonConvert.DeserializeObject<KeyValuePair<string, dynamic>>(UTF8Encoding.UTF8.GetString(data));
res = new Tuple<string, dynamic>(dat.Key, dat.Value);
}
return res;
}
The tools.ReadEntry(data) returns a byte[] containing the data, from the binary formatted file.
Here is the class KeyValuePair<K, V>
[Serializable]
internal struct KeyValuePair<K, V> {
public K Key { get; set; }
public V Value { get; set; }
}
You can check if it's a JArray and implement special handling. E.g.
byte[] data = Encoding.UTF8.GetBytes(#"{""Key"": ""Something"", ""Value"": [""test"", ""test 2"", ""test 3""]}");
var dat = JsonConvert.DeserializeObject<KeyValuePair<string, dynamic>>(UTF8Encoding.UTF8.GetString(data));
var value = dat.Value;
if (value is JArray)
{
var arrayType = value[0].Value.GetType().MakeArrayType();
value = value.ToObject(arrayType);
}
var res = new Tuple<string, dynamic>(dat.Key, value);
Just call DeserializeObject<T> replacing T with the type you intend to deserialize the input string into and json.NET will take care of the rest.
string[] json = JsonConvert.DeserializeObject<string[]>(inputString);
EDIT:
Ok, so assuming all of your json is in the form of the example posted in EDIT 3 then waht you really want is;
public class KVPair
{
public string Key { get; set; }
public string[] Value { get; set; }
}
KVPair pair = JsonConvert.DeserializeObject<KVPair>(UTF8Encoding.UTF8.GetString(data));
Now this is fairly static but I'm not sure you actually need dynamic. If you do then you'll want the Value property to be of type object or dynamic. However, if you go that route then you will unfortunately have to deal with this unknown type. I'm really not knowledgeable on the dynamic type so I can't comment on how to deal with it later on but if say for example, the array could contain, ints, floats or strings and you made Value of type object you would have inspect the array later on, determine the underlying type and cast each of the items to that type before you could do anything useful with them. Hope that helps. If you're lucky you'll just be able to use the code I posted above as it's far simpler and is actually type safe.