So i'm getting a response like this
{"$id":"1","success":true,"errors":{"$id":"2","$values":[]}}
how can i convert this into to a c# object, tried using this(http://json2csharp.com/) tool to make an output but it doesn't make sense
this is what i'm getting
x
public class Errors
{
public string __invalid_name__$id { get; set; }
public List<object> __invalid_name__$values { get; set; }
}
public class RootObject
{
public string __invalid_name__$id { get; set; }
public bool success { get; set; }
public Errors errors { get; set; }
}
I'm kinda new to c#, any inputs would be deeply appreciated, i basically need access to success key variable
You need to add [JsonProperty] attribute to every property that key name started with dollar $
public class Errors
{
[JsonProperty("$id")]
public string id { get; set; }
[JsonProperty("$values")]
public List<object> values { get; set; }
}
public class RootObject
{
[JsonProperty("$id")]
public string id { get; set; }
public bool success { get; set; }
public Errors errors { get; set; }
}
Because the $ indicates metadata, not an actual data field. so you have to modify your JsonSerializerSettings to ignore MetadataPropertyHandling.
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.MetadataPropertyHandling = MetadataPropertyHandling.Ignore;
And finally deserialize your json to above class objects.
RootObject rootObject = JsonConvert.DeserializeObject<RootObject>(json, settings);
Here I created a sample console app for demonstration purpose that shows how above code will work.
class program
{
public static void Main()
{
string json = File.ReadAllText(#"Path to your json file");
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.MetadataPropertyHandling = MetadataPropertyHandling.Ignore;
RootObject rootObject = JsonConvert.DeserializeObject<RootObject>(json, settings);
Console.WriteLine("id: " + rootObject.id);
Console.WriteLine("success: " + rootObject.success);
Console.WriteLine("errors.id: " + rootObject.errors.id);
Console.WriteLine("errors.values: " + string.Join(",", rootObject.errors.values));
Console.ReadLine();
}
}
Output:
Well, What you can do is
public class Errors
{
[JsonProperty(PropertyName = "$id")]
public string id { get; set; }
[JsonProperty(PropertyName = "$values")]
public List<object> values { get; set; }
}
public class RootObject
{
[JsonProperty(PropertyName = "$id")]
public string id { get; set; }
public bool success { get; set; }
public Errors errors { get; set; }
}
You need your object attributes to match you json string ($id instead of _invalid_name_$id), then you can use:
JsonConvert.DeserializeObject<RootObject>(jsonString);
Here is a simple class to serialize json string from object or to object (T). May de/serialize array(list) of objects.
public class HelperSerializer<T> where T: class
{
public static string WriteFromObject(T source)
{
using (var ms = new MemoryStream()) {
var ser = new DataContractJsonSerializer(typeof(T));
ser.WriteObject(ms, source);
byte[] json = ms.ToArray();
return Encoding.UTF8.GetString(json, 0, json.Length);
}
}
// Deserialize a JSON stream to an object.
public static T ReadToObject(string json)
{
using (var ms = new MemoryStream(Encoding.UTF8.GetBytes(json)))
{
var ser = new DataContractJsonSerializer(typeof(T));
return ser.ReadObject(ms) as T;
}
}
}
Use persons = HelperSerializer<List<Person>>.ReadToObject(json);
and var json = HelperSerializer<List<Person>>.WriteFromObject(persons);
Related
All - I've stumbled into a scenario that's causing me quite a bit of grief. I have a json structure (produced by gateio api) which on the face of it, looks super simple to deserialize into an object. the jsonTickerString looks like the below:
{
"method":"ticker.update",
"params":[
"BTC_USDT",
{
"period":86400,
"open":"46721.06",
"close":"48130.43",
"high":"48758.59",
"low":"46330.3",
"last":"48130.43",
"change":"2.95",
"quoteVolume":"2246.8399550054",
"baseVolume":"106183751.468785134437"
}
],
"id":null
}
However, this is proving to be deceptively funky when trying to push it into an object model. I derived the object model below and thought we were all set to go:
public partial class GateIoTicker
{
[JsonProperty("method")]
public string Method { get; set; }
[JsonProperty("params")]
public List<ParamElement> Params { get; set; }
[JsonProperty("id")]
public object Id { get; set; }
}
public class ParamClass
{
[JsonProperty("period")]
public long Period { get; set; }
[JsonProperty("open")]
public string Open { get; set; }
[JsonProperty("close")]
public string Close { get; set; }
[JsonProperty("high")]
public string High { get; set; }
[JsonProperty("low")]
public string Low { get; set; }
[JsonProperty("last")]
public string Last { get; set; }
[JsonProperty("change")]
public string Change { get; set; }
[JsonProperty("quoteVolume")]
public string QuoteVolume { get; set; }
[JsonProperty("baseVolume")]
public string BaseVolume { get; set; }
}
public partial struct ParamElement
{
public string coinName;
public ParamClass quoteParams;
public static implicit operator ParamElement(ParamClass quoteparams)
{
return new ParamElement { quoteParams = quoteparams };
}
public static implicit operator ParamElement(string coinname)
{
return new ParamElement { coinName = coinname };
}
}
I then set about populating the object using the standard Json.Net approach:
var gateIoTicker = JsonConvert.DeserializeObject<GateIoTicker>(jsonTickerString);
However, although this correctly deserializes the string element in the "params" object, no amount of coersion will bring about a deserialization of the ParamClass object.
Am I missing something very obvious here?? I've spent an inordinate amount of time trying to figure this out and think it's now time to solicit some superior brain power.
Hope this scans as expected...
[Edit] - further to Serge's suggestion, i took his code and added it as a method on my GatIoTicker object. Would have preferred an option that desrializes using attributes, but this works perfectly. Refactored code looks like:
public partial class GateIoTicker
{
[JsonProperty("method")]
public string Method { get; set; }
[JsonProperty("params")]
public List<ParamElement> Params { get; set; }
[JsonProperty("id")]
public object Id { get; set; }
public GateIoTicker FromJson(string json)
{
var jsonObject = JObject.Parse(json);
var pars = jsonObject["params"] as JArray;
var paramElement = new ParamElement();
foreach (var jObject in pars)
{
if (jObject.GetType().Name.ToString() == "JValue") paramElement.ParamName = ((JValue)jObject).ToString();
else
{
paramElement.ParamBody = jObject.ToObject<ParamClass>();
}
}
GateIoTicker gateIoTicker = new GateIoTicker { Params = new List<ParamElement>() };
gateIoTicker.Id = (string)jsonObject["Id"];
gateIoTicker.Method = (string)jsonObject["method"];
gateIoTicker.Params.Add(paramElement);
return gateIoTicker;
}
}
public partial class ParamElement
{
public string ParamName { get; set; }
public ParamClass ParamBody {get; set;}
}
thanks again for the suggestions and nudges. seasons greetings
Try this, it was tested in Visual studio
var jsonObject = JObject.Parse(json);
var pars = jsonObject["params"] as JArray;
var paramElement = new ParamElement();
foreach (var jObject in pars)
{
if (jObject.GetType().Name.ToString() == "JValue") paramElement.ParamName = ((JValue)jObject).ToString();
else
{
paramElement.ParamBody=jObject.ToObject<ParamClass>();
}
}
GateIoTicker gateIoTicker = new GateIoTicker {Params= new List<ParamElement>()};
gateIoTicker.Id= (string) jsonObject["Id"];
gateIoTicker.Method= (string) jsonObject["method"];
gateIoTicker.Params.Add(paramElement);
ParamElement class
public partial class ParamElement
{
public string ParamName { get; set; }
public ParamClass ParamBody {get; set;}
}
[SOLVED] applied given solution, works fine!
Aim of the program: Save/reload previous data when user opens and closes the program.
I used to (de)serialize successfully with one object(obj), now I have two different objects of different classes.
I tried to combine them by looking at other posts; I put them in object array and give that object array when (de)serializing as parameter.
I do initialize for example like this; obj.flag1 = true; before
calling serialize() in other methods.(I didn't put them for simplicity since I already stated the functionality of methods)
It says objects are null, but logically if obj2 and obj were null, it should have given the error for obj standalone. It won't read empty file I handled it. The moment I tried to combine two object it started to give me null error for both of them. I am about to rip my hair, can someone please help?
[Serializable]
public partial class UI : Form
{
FlagClass obj;
CurrentAmplitude obj2;
object[] seri_obj;//combine multiple objects
//deserialization is performed in constructor
public UI()
{
InitializeComponent();
seri_obj = new object[] { obj, obj2 };
input += ".txt";
//default path + new filename
path_combined = Path.Combine(root, input);
//it won't try to read empty file
if (!File.Exists(path_combined))
{
using (var stream = File.Create(path_combined))
{
}
}
else //already have that file,so when user opens the program, data is loaded from file
{
//read booleans and inetegres
string json2 = File.ReadAllText(path_combined);
string FormattedJson = FormatJson(json2);
seri_obj = JsonConvert.DeserializeObject<object[]>(FormattedJson);
}
}
private static string FormatJson(string json)
{
dynamic parsedJson = JsonConvert.DeserializeObject(json);
return JsonConvert.SerializeObject(parsedJson, Formatting.Indented);
}
//I do serialization here
void Serialize()
{
string json = JsonConvert.SerializeObject(seri_obj, Formatting.Indented);
File.WriteAllText(path_combined, json);
}
String values are in this class via "obj2"
[Serializable]
class CurrentAmplitude
{
//this class has the string values
[JsonProperty(PropertyName = "value1")]
public int value1 { get; set; }
[JsonProperty(PropertyName = "value2")]
public string value2 { get; set; }
[JsonProperty(PropertyName = "value3")]
public string value3 { get; set; }
[JsonProperty(PropertyName = "value4")]
public string value4 { get; set; }
[JsonProperty(PropertyName = "value5")]
public string value5 { get; set; }
public CurrentAmplitude(){
}
}
Boolean values are in this class via "obj"
[Serializable]
class FlagClass
{
//this class has the boolean values
[JsonProperty(PropertyName = "flag1")]
public bool flag1 { get; set; }
[JsonProperty(PropertyName = "flag2")]
public bool flag2 { get; set; }
public FlagClass()
{
}
}
Where you are deserializing:-
seri_obj = JsonConvert.DeserializeObject<object[]>(FormattedJson);
You are asking the deserializer to return an array raw objects, which will result in an array of JObject types, not your FlagClass and CurrentAmplitude types.
You're also setting seri_obj, but never assigning the values in seri_obj to your obj or obj2 variables, which is why the compiler is warning you.
You would be better off having an umbrella configuration class like this:-
class Configuration
{
public Flag { get; set; } = new FlagClass();
public CurrentAmplitude { get; set; } = new CurrentAmplitude();
}
Then just deserialize/serialize an instance of your Configuration class when you want to load/save...
// create config object if new
var config = new Configuration();
// to save
var json = JsonConvert.SerializeObject(config);
// to load
var config = JsonConvert.DeserializeObject<Configuration>(json);
// get/set config values
config.Flag.flag2 = false;
Here is a more complete example:-
void Main()
{
// create a new blank configuration
Configuration config = new Configuration();
// make changes to the configuration
config.CurrentAmplitude.value1 = 123;
config.CurrentAmplitude.value2 = "Hello";
config.FlagClass.flag1 = false;
config.FlagClass.flag2 = true;
// serialize configuration to a string in order to save to a file
string json = JsonConvert.SerializeObject(config);
// reload config from saved string
config = JsonConvert.DeserializeObject<Configuration>(json);
// should print "Hello"
Console.WriteLine(config.CurrentAmplitude.value2);
}
class Configuration
{
public CurrentAmplitude CurrentAmplitude { get; set; } = new CurrentAmplitude();
public FlagClass FlagClass { get; set; } = new FlagClass();
}
class CurrentAmplitude
{
public int value1 { get; set; }
public string value2 { get; set; }
public string value3 { get; set; }
public string value4 { get; set; }
public string value5 { get; set; }
}
class FlagClass
{
public bool flag1 { get; set; }
public bool flag2 { get; set; }
}
Pre C# 6, your config class would look like this:-
class Configuration
{
public Configuration()
{
CurrentAmplitude = new CurrentAmplitude();
FlagClass = new FlagClass();
}
public CurrentAmplitude CurrentAmplitude { get; set; }
public FlagClass FlagClass { get; set; }
}
I am trying to get the modhash value from a returned json string, I have set my getter/setter
public string mod_hash { get; set; }
I am using httclient, how can I get the json value of mod_hash
To post data:
/
Try with the below one.
To deserialize,you need to create the proper class structure for the json string. As per your json string, i have created here. Try and let us know if you have still issues.
public class RootObject
{
public Json json { get; set; }
}
public class Json
{
public List<object> errors { get; set; }
public Data data { get; set; }
}
public class Data
{
public bool need_https { get; set; }
public string modhash { get; set; }
public string cookie { get; set; }
}
And to test if it is correct or not here i have the program to get the "modhash" property value from your json string.
class Program
{
static void Main(string[] args)
{
string jsonstring = #"{ ""json"": {""errors"": [],""data"": { ""need_https"": true, ""modhash"": ""valuehereremoved"",""cookie"": ""valuehereremoved"" } } }";
var serializer = new JavaScriptSerializer();
var jsonObject = serializer.Deserialize<RootObject>(jsonstring);
Console.WriteLine("modhash : " + jsonObject.json.data.modhash);
Console.Read();
}
}
OUTPUT
Hope it solves your problem.
Hi I have a response from the web service and i would like to have a single url from the response.
My response is in the below format.
[{"cdn_streaming_uri": "9e849cfbb2e157-22558a0600b387d0abe240fe5.r73.stream..rackcdn.com", "name": "test1", "cdn_ios_uri": "d3d4c27-22558a0600b387d0abc071d0ae240kcdn.com", "cdn_ssl_uri": "https://990fea26e-22558a0600b387d0abc071d0ae240fe5.ssl.cdn.com", "cdn_enabled": false, "ttl": 259200, "log_retention": false, "cdn_uri": "99b56a009-22558a0600b3c071d0ae240fe5.r73.n.com"}, {"cdn_streaming_uri": "74ec8c-d5edc6cad91792413b1b134fde.r46.stcdn.com", "name": "test2", "cdn_ios_uri": "d05437e44-d5edc61792413b1b134fde.iosr.cdn.com", "cdn_ssl_uri": "https://a1c2ebbf5-d5edc6cd91792413b1b134fde.scdn.com", "cdn_enabled": false, "ttl": 259200, "log_retention": false, "cdn_uri": "72ffd-d5edc6ca16852413b1b134fde.cdn.com"}, {"cdn_streaming_uri": "93665b76-550971032c2a22cdn.com", "name": "test3", "cdn_ios_uri": "ca6b-550971032c2fbf19452d6a.iosr.cf2.rackcdn.com", "cdn_ssl_uri": "https://c7c39-550971032cbf19452d6cdn.com", "cdn_enabled": true, "ttl": 86400, "log_retention": true, "cdn_uri": "68fc6d831a94-550971032c252d6a.r3cdn.com"}]
I need to the "cdn_streaming_uri" for the name "test3".
You can view the JSON parser in http://json.parser.online.fr/
How do i parse it?
Here is my code:
public static object getTokenResponse(String PrivateURL, string ResponseType)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(PrivateURL +"?format=JSON");
request.Method = "GET";
request.Headers.Add("X-Auth-Token", id);
//request.ContentType = "application/XML";
HttpWebResponse resp1;
try
{
resp1 = (HttpWebResponse)request.GetResponse();
}
catch (Exception exp)
{
string[] st = new string[0];
return st;
}
StreamReader reader = new StreamReader(resp1.GetResponseStream());
string secondresponse = reader.ReadToEnd();
Console.WriteLine(secondresponse);
reader.Close();
JavaScriptSerializer json_serializer = new JavaScriptSerializer();
object obj1 = json_serializer.DeserializeObject(secondresponse);
}
I could see the response in obj1.
The best approach, I think, is to create class which will represent your response. The easiest way is to use Visual Studio's EDIT -> Paste Special -> Paste JSON As Classes option:
You just copy your response and paste it as JSON classes. Visual studio will generate model for you. In this particular case the result will be:
namespace ConsoleApplication91
{
public class Rootobject
{
public Class1[] Property1 { get; set; }
}
public class Class1
{
public string cdn_streaming_uri { get; set; }
public string name { get; set; }
public string cdn_ios_uri { get; set; }
public string cdn_ssl_uri { get; set; }
public bool cdn_enabled { get; set; }
public int ttl { get; set; }
public bool log_retention { get; set; }
public string cdn_uri { get; set; }
}
}
which, of course, does not look very nice, but you're always welcome to refactor this code. When you have your model you download your response, parse it and get what you need using linq, for example:
using (var client = new WebClient())
{
var url = "your service url";
var serializer = new JavaScriptSerializer();
// Response in JSON format
var respJson = client.DownloadString(url);
// Deserialized response
var resp = serializer.Deserialize<Rootobject>(respJson);
// Your requested result
var result = resp.Property1.FirstOrDefault(o => o.name == "test3").cdn_streaming_uri;
}
EDITS:
After refactoring (using DataMember attributes and removing redundant model objects) you can have the following model:
[DataContract]
public class Model
{
[DataMember(Name = "cdn_streaming_uri")]
public string CdnStreamingUri { get; set; }
[DataMember(Name = "name")]
public string Name { get; set; }
[DataMember(Name = "cdn_ios_uri")]
public string CdnIosUri { get; set; }
[DataMember(Name = "cdn_ssl_uri")]
public string CdnSslUri { get; set; }
[DataMember(Name = "cdn_enabled")]
public bool CdnEnabled { get; set; }
[DataMember(Name = "ttl")]
public int Ttl { get; set; }
[DataMember(Name = "log_retention")]
public bool LogRetention { get; set; }
[DataMember(Name = "cdn_uri")]
public string CdnUri { get; set; }
}
After some research I've figured out that JavascriptSerializer is a little deprecated and it does not support any kind of DataMemberAttributes. So I would recommend to use DataContractJsonSerializer. It is little messier than JavascriptSerializer but I think it's fine. If you do not care about any code conventions you can peacefully use the firs provided option (with JavaScriptSerializer and no DataMember attributes). And do not forget to update result query:
using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(respJson)))
{
var serializer = new DataContractJsonSerializer(typeof(Model[]));
var resp = serializer.ReadObject(ms) as Model[];
var result = resp.FirstOrDefault(o => o.Name == "test3").CdnStreamingUri;
}
But, also, if you don't want to use linq (which I'm still strongly recommend) you can create some function which will find the CdnStreamingUri you need:
public static class Extensions
{
public static string GetCdnStreamingUriFor(this Model[] input, string name)
{
foreach (var model in input)
{
if (model.Name == name)
return model.CdnStreamingUri;
}
return string.Empty;
}
}
And your result query will look like:
var result = resp.GetCdnStreamingUriFor("test3");
P.S.
Full list of all used namespaces:
using System;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Json;
using System.Text;
using System.Runtime.Serialization;
I recommend you to generate class for that json, like the following (http://json2csharp.com/ ):
public class RootObject
{
public string cdn_streaming_uri { get; set; }
public string name { get; set; }
public string cdn_ios_uri { get; set; }
public string cdn_ssl_uri { get; set; }
public bool cdn_enabled { get; set; }
public int ttl { get; set; }
public bool log_retention { get; set; }
public string cdn_uri { get; set; }
}
After that you can deserialize strongly typed object http://msdn.microsoft.com/en-us/library/bb355316(v=vs.110).aspx
Help to deal with JSON deserialization correct answer. For example, we have JSON response to the following:
{"variant":"otvet1",
"source":"otvet2",
"items":[
{"list":"512"},
{"vist":"315"},
{"zist":"561"}]}
To deserialize using the following code:
[DataContract]
public partial class ItemsList
{
[DataMember(Name = "list")]
public string lisType { get; set; }
[DataMember(Name = "vist")]
public string vistType { get; set; }
[DataMember(Name = "zist")]
public string zistType { get; set; }
}
[DataContract]
public partial class SourceList
{
[DataMember(Name = "variant")]
public string variantType { get; set; }
[DataMember(Name = "source")]
public string vistType { get; set; }
[DataMember(Name = "items")]
public List <ItemsList> TestItemsList { get; set; }
}
public class JsonStringSerializer
{
public static T Deserialize<T>(string strData) where T : class
{
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(strData));
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
T tRet = (T)ser.ReadObject(ms);
ms.Close();
return (tRet);
}
}
private static SourceList SourceTempList;
SourceTempList = JsonStringSerializer.Deserialize<SourceList>(e.Result); //in e.Result JSON response
In the previous code, it works, but if you change the JSON response, it does not work ...
New JSON response:
{"variant":"otvet1",
"source":"otvet2",
"items":[3,
{"list":"512"},
{"vist":"315"},
{"zist":"561"}]}
In this case, c # code for deserialization does not work ...
Items in the number 3 appeared, tell me how to deserialize the JSON response to this?
Were available to list vist and zist ...Help me...please
Historically the DataContractJsonSerializer has been seen as broken. The reccomendation is to use JSON.Net http://james.newtonking.com/projects/json-net.aspx
Check out Deserialization problem with DataContractJsonSerializer