I have a problem with deserialization.
It's my json structure
{ "status": "ok",
"data": [
{
"issued": 1447358848072,
"volume": "5.52565454",
"currency": "pln",
"limit": "724.2500",
"type": "bid",
"id": "2015/11/12/13328345/4836"
},
{
"issued": 1447359927423,
"volume": "1.25465440",
"currency": "pln",
"limit": "1850.5000",
"type": "ask",
"id": "2015/11/12/13328342/8188"
}
]
}
It's my class in C# and functions:
public class oferta
{
public string issued { get; set; }
public string volume { get; set; }
public string currency { get; set; }
public string limit { get; set; }
public string type { get; set; }
public string id { get; set; }
}
public class tBitCurex_PRV_Offers
{
public string status { get; set; }
public List<oferta> data { get; set; }
}
public void GetPRV_Offers(tBitCurex_PRV_Offers B)
{
try
{
var RSP = "my json string";
B = JsonConvert.DeserializeObject<tBitCurex_PRV_Offers>(RSP);
if (B.data.Count > 0)
{
// in here COUNT = 2 and all works fine.
// and B.status = "ok"
// but when function is end i have a null
}
}
catch (Exception oException)
{
MessageBox.Show(oException.Message);
}
}
public void Pobierz_PRV_Offers()
{
try
{
var BitCurexOfers = new tBitCurex_PRV_Offers();
GetPRV_Offers(BitCurexOfers);
if (BitCurexOfers.status == "ok")
{
// do something with BitcurexOffers;
// I have a NULL if a use deserialize.
}
}
catch
{
sbInfo2.Text = "Error..xxxx";
}
finally
{
Application.DoEvents();
}
}
When in similar fuction i use
JObject oObject = JObject.Parse("json string");
B.status = (string)oObject["status"];
then all works fine inside and outside the function.
How should i do this properly with JsonConvert.DeserializeObject ???
Your problem is not with deserialization but with reference pointers
Instead of void, change the return type of the Function to BitCurex_PRV_Ofers and at the end of the function return B; and assign BitCurexOfers to the result of the function call instead of instantiating a new instance
Or just change the parameter to
ref BitCurex_PRV_Ofers B)
This is happening because you get a pointer to BitCurexOfers in B, then change that pointer with the result of deserialization
If you use JsonConvert.Poupulate(B); this will also work for you without any other changes
Your problem is that you're not altering B in the caller, just the method in which you're doing the deserialization. You can either change B to a ref parameter, or you can return it from the method instead.
Your sample code has some errors. try adding this attribute and it should work.
[Newtonsoft.Json.JsonObject(Title = "root")]
public class tBitCurex_PRV_Offers
Related
I'm using PostAsJsonAsync in the HttpClient to query Elastic, and it's failing on line 12, "wildcard"
I used https://json2csharp.com/ to convert the example JSON to C# objects.
This is the json that's being produced by Newtonsoft which fails.
{
"query": {
"bool": {
"must": [
{
"range": {
"#timestamp": {
"gte": "now-7d",
"lt": "now"
}
},
"wildcard": {
"request.keyword": {
"value": "/message/*/*-message/2c35669dd87e471faad1f90374d8d380/status",
"case_insensitive": true
}
}
}
]
}
}
}
This is an example that I was provided and used to convert the json to C# objects.
{
"query": {
"bool": {
"must": [
{
"range": {
"#timestamp": {
"gte": "now-7d",
"lt": "now"
}
}
},
{
"wildcard": {
"request.keyword": {
"value": "/message/*/*-message/2c35669dd87e471faad1f90374d8d380/status",
"case_insensitive": true
}
}
}
]
}
}
}
Both are valid JSON, but only the 2nd one is accepted by Elastic. It's seems to be expecting curly braces around the properties in must, but I can't figure out how to get the JSON to serialize this way.
You are encountering a limitation with code-generation tools such as https://json2csharp.com/, namely that they do not handle implied polymorphism very well. In such cases you may need to manually fix the generated classes.
Consider the following JSON array containing two different types of object:
[{"A" : "a value"},{"B" : "b value"}]
The array contains objects that either have a property A or a property B, but if you generate classes from this JSON, you will get a single, merged type with both properties:
public class Root
{
public string A { get; set; }
public string B { get; set; }
}
Whereas what you really want is something like:
public interface IRootBase { }
public class A : IRootBase
{
public string A { get; set; }
}
public class B : IRootBase
{
public string B { get; set; }
}
Given such a model, you will be able to construct a List<IRootBase> and serialize it to get the JSON shown. (And, to deserialize, see Deserializing polymorphic json classes without type information using json.net.)
In your case, the problem is with the array value of "must". As you can see this array contains two different types of object:
[
{
"range":{
"#timestamp":{
"gte":"now-7d",
"lt":"now"
}
}
},
{
"wildcard":{
"request.keyword":{
"value":"/message/*/*-message/2c35669dd87e471faad1f90374d8d380/status",
"case_insensitive":true
}
}
}
]
But https://json2csharp.com/ will create the following combined type:
public class Must
{
public Range range { get; set; }
public Wildcard wildcard { get; set; }
}
If you were to create an array with a single instance of Must containing both properties, you would get the invalid JSON rejected by Elastic.
Instead, you need to manually modify the auto generated types as follows:
#region Manually created from Must
public interface IMustConstraint { }
public class RangeConstraint : IMustConstraint
{
public Range range { get; set; }
}
public class WildcardConstraint : IMustConstraint
{
public Wildcard wildcard { get; set; }
}
#endregion Manually created from Must
public class Range
{
[JsonProperty("#timestamp")]
public Timestamp Timestamp { get; set; }
}
public class Timestamp
{
public string gte { get; set; }
public string lt { get; set; }
}
public class Wildcard
{
[JsonProperty("request.keyword")]
public RequestKeyword RequestKeyword { get; set; }
}
public class RequestKeyword
{
public string value { get; set; }
public bool case_insensitive { get; set; }
}
public class BoolQuery // Renamed from Bool for clarity
{
public List<IMustConstraint> must { get; set; } // Modified from List<Must>
}
public class Query
{
public BoolQuery #bool { get; set; }
}
public class Root
{
public Query query { get; set; }
}
And now you will be able to do:
Root root = new ()
{
query = new ()
{
#bool = new ()
{
must = new ()
{
new RangeConstraint() { range = new () { Timestamp = new () { gte = "now-7d", lt = "now" } } },
new WildcardConstraint() { wildcard = new () { RequestKeyword = new () { value = "/message/*/*-message/2c35669dd87e471faad1f90374d8d380/status", case_insensitive = true } } },
},
},
},
};
var json = JsonConvert.SerializeObject(root, Formatting.Indented);
And create your required JSON.
Demo fiddle here.
I created a class for a json object (not automatically).
However, I don't quite understand how to make the button object contain nameless arrays as in the example?
Example JSON (what the server expects to receive):
{
"one_time":false,
"buttons":[
[
{
"action":{
"type":"location",
"payload":"{\"button\": \"1\"}"
}
}
],
[
{
"action":{
"type":"open_app",
"app_id":6232540,
"owner_id":-157525928,
"hash":"123",
"label":"LiveWidget"
}
}
],
[
{
"action":{
"type":"vkpay",
"hash":"action=transfer-to-group&group_id=181108510&aid=10"
}
}
],
[
{
"action":{
"type":"text",
"payload":"{\"button\": \"1\"}",
"label":"Red"
},
"color":"negative"
},
{
"action":{
"type":"text",
"payload":"{\"button\": \"2\"}",
"label":"Green"
},
"color":"positive"
},
{
"action":{
"type":"text",
"payload":"{\"button\": \"2\"}",
"label":"Blue"
},
"color":"primary"
},
{
"action":{
"type":"text",
"payload":"{\"button\": \"2\"}",
"label":"White"
},
"color":"secondary"
}
]
]
}
Keyboard.cs (manually created class)
public class Keyboard
{
public bool one_time { get; set; }
public List<buttons> buttons { get; set; }
}
public class buttons
{
public action action { get; set; }
public string color { get; set; }
}
public class action
{
public string type { get; set; }
public string payload { get; set; }
public string label { get; set; }
}
I create an object like this:
var Keyboard_obj = new Keyboard()
{
one_time = false,
buttons = new List<buttons>()
{
new buttons()
{
action = new action()
{
type = "test1",
label = "class obj",
payload = "{\"button\": \"1\"}"
},
color = "negative"
},
new buttons()
{
action = new action()
{
type = "test2",
label = "class obj",
payload = "{\"button\": \"2\"}"
},
color = "positive"
}
}
};
How can I remake the class so that I get a JSON object like the example above?
You should use JsonSerializer
this code will give you a Json object like the example above:
var output = JsonConvert.SerializeObject(Keyboard_obj );
you can also create an object from Json:
Keyboard keyboard = JsonConvert.DeserializeObject<Keyboard>(output );
I can suggest you to try using dynamic objects
dynamic myObject = JsonConvert.DeserializeObject<dynamic>(input);
decimal Amount = Convert.ToDecimal(myObject.Amount);
string Message = myObject.Message;
If you take your JSON and use Visual studio (use paste as special option) or online tool to generate classes from the provided JSON then following classes will be generated.
Note - RootBoject.buttons Is an array or array instead of single collection.
public class Rootobject
{
public bool one_time { get; set; }
public Button[][] buttons { get; set; }
}
public class Button
{
public Action action { get; set; }
public string color { get; set; }
}
public class Action
{
public string type { get; set; }
public string payload { get; set; }
public int app_id { get; set; }
public int owner_id { get; set; }
public string hash { get; set; }
public string label { get; set; }
}
So with the provided class schema if you use JsonConvert to searialize the RootObject then you will get the required JSON.
i have a solution where i consume a WebService using RestSharp providing JSON data. I have a class model like this, matching the received data:
public class PBase
{
public string Name { get; set; }
public virtual string GetValue()
{
return string.Empty;
}
}
public class PDouble : PBase
{
public double DoubleValue { get; set; }
public string Scale { get; set; }
public override string GetValue()
{
return DoubleValue.ToString(CultureInfo.InvariantCulture);
}
}
public class PBool : PBase
{
public bool? BoolValue { get; set; }
public override string GetValue()
{
if (!BoolValue.HasValue)
return null;
return BoolValue.Value ? "1" : "0";
}
}
Meerely deep within the data, such blocks as the following appear multiple times, holding the parameters of a parent object, which is not of much interest here (as everything else except the parameter thingy works fine):
"Parameters":
[
{
"__type": "PDouble:http://name.space.de/Parameter",
"Name": "DEPTH",
"DoubleValue": 5,
"Scale": "MM"
},
{
"__type": "PDouble:http://name.space.de/Parameter",
"Name": "HEIGHT",
"DoubleValue": 10,
"Scale": "MM"
},
{
"__type": "PBool:http://name.space.de/Parameter",
"Name": "ESSENTIAL",
"BoolValue": true
},
]
Now, the problem is, the deserialized data contains only PBase instances. So everything except Name is gone. How can i achieve correct deserialization?
EDIT:
For deserialization i have nothing special implemented, just like this:
var client = new RestClient()
{
BaseUrl = new Uri("MyURL")
};
var request = new RestRequest()
{
Resource = "MyResource",
Method = Method.GET
};
request.AddHeader("Accept", "application/json");
request.RequestFormat = DataFormat.Json;
var response = client.Execute<MyType>(request);
return response.Data;
How can I query (to see if a property exists) and enumerate (the array property) found within a complex JSON object using using JSON.NET in C# ?
I am receiving a complex JSON object from an API with a variable number/type of properties.
I keep reading the JSON.Net Documentation, reviewing samples, etc. but not gotten far and am lost in JObject, JArray, JToken, using dynamic, etc...
I want to find the pageResponses.scriptOutput property, verify it contains and .items[] array and then enumerate/iterate the array.
Edit
I made progress and found typo in JSON data example.
But how can I query/enumerate the child objects using key names, e.g.(item.location, item.timestamp) ?
string json = File.ReadAllText(#"Output.json");
JObject jObj = JObject.Parse(json);
IList<JToken> items = jObj["pageResponses"][0]["scriptOutput"]["items"].ToList();
foreach (JToken item in items){
Console.WriteLine(item["location"]);
}
/*** Console Output ***/
// Austin, TX
// Anaheim, CA
// Adams, MN
// Barstow, CA
var varItems = from o in jObj["pageResponses"][0]["scriptOutput"]["items"].ToList() select o;
foreach (var item in varItems){
Console.WriteLine(item["timestamp"]);
}
/*** Console Output ***/
// 2016 - 05 - 03 19:53
// 2016 - 05 - 04 04:10
// 2016 - 05 - 04 08:18
// 2016 - 05 - 01 12:26
(JSON sample below trimmed down for brevity)
{
"meta": {
"outputAsJson": true,
"backend": {
"os": "linux",
"id": "10.240.0.3_2",
"requestsProcessed": 8
}
},
"pageResponses": [
{
"pageRequest": {
"renderType": "script",
"outputAsJson": true
},
"frameData": {
"name": "",
"childCount": 1
},
"events": [
{
"key": "navigationRequested",
"time": "2016-05-06T13:43:30.344Z"
},
{
"key": "navigationRequested",
"time": "2016-05-06T13:43:31.131Z"
}
],
"scriptOutput": {
"items": [
{
"location": "Austin, TX",
"timestamp": "2016-05-03 19:53",
"title": "User Login"
},
{
"location": "Anaheim, CA",
"timestamp": "2016-05-04 04:10",
"title": "User Logout"
},
{
"location": "Adams, MN",
"timestamp": "2016-05-04 08:18",
"title": "User Login"
},
{
"location": "Barstow, CA",
"timestamp": "2016-05-01 12:26",
"title": "User Logout"
}
]
},
"statusCode": 200
}
],
"statusCode": 200,
"content": {
"name": "content.json",
"encoding": "utf8"
},
"originalRequest": {
"pages": [
{
"renderType": "script",
"outputAsJson": true
}
]
}
}
I suggest creating a proxy class (I used json2csharp):
public class Backend
{
public string os { get; set; }
public string id { get; set; }
public int requestsProcessed { get; set; }
}
public class Meta
{
public bool outputAsJson { get; set; }
public Backend backend { get; set; }
}
public class PageRequest
{
public string renderType { get; set; }
public bool outputAsJson { get; set; }
}
public class FrameData
{
public string name { get; set; }
public int childCount { get; set; }
}
public class Event
{
public string key { get; set; }
public string time { get; set; }
}
public class ScriptOutput
{
public List<object> items { get; set; }
}
public class PageRespons
{
public PageRequest pageRequest { get; set; }
public FrameData frameData { get; set; }
public List<Event> events { get; set; }
public ScriptOutput scriptOutput { get; set; }
public int statusCode { get; set; }
}
public class Content
{
public string name { get; set; }
public string encoding { get; set; }
}
public class Page
{
public string renderType { get; set; }
public bool outputAsJson { get; set; }
}
public class OriginalRequest
{
public List<Page> pages { get; set; }
}
public class RootObject
{
public Meta meta { get; set; }
public List<PageRespons> pageResponses { get; set; }
public int statusCode { get; set; }
public Content content { get; set; }
public OriginalRequest originalRequest { get; set; }
}
Then deserialize it:
var obj = JsonConvert.DeserializeObject<RootObject>(json);
if (obj != null && obj.pageResponses != null)
{
foreach (var pageResponse in obj.pageResponses)
{
if (pageResponse.scriptOutput == null)
continue;
foreach (var item in pageResponse.scriptOutput.items)
{
Console.WriteLine(item);
}
}
}
I do this with a couple of Extension Methods and I use JsonConvert.DeserializeObject.
Code snippets below.
Usage
ExpandoObject data = JsonConvert.DeserializeObject<ExpandoObject>(jsonString);
if(data.HasProperty("propertyToCheck"))
{
object[] objects = data.Get<object[]>("propertyToCheck");
}
In the snippet above I check a property exists, then I assign it to a .Net type, in this case an object array. Though it can be any type so long as it's sane.
Extension Methods
public static bool HasProperty(this ExpandoObject value, string property)
{
bool hasProp = false;
if (((IDictionary<String, object>)value).ContainsKey(property))
{
hasProp = true;
}
return hasProp;
}
public static T Get<T>(this ExpandoObject value, string property)
{
return (T)((IDictionary<String, dynamic>)value)[property];
}
Quick, easy and to the point!
I am trying to access the "success" property to get its value. Right now, it is hitting catch saying "Object reference not set to an instance of an object. " How do I get the string value?
{ "success": true, "next": "/locations", "amount": 325, "keys": 3,
"credits": 6185}
private static void postComplete(object sender, UploadStringCompletedEventArgs e)
{
object result = JsonConvert.DeserializeObject<object>(e.Result);
try{
PropertyInfo pi = result.GetType().GetProperty("success");
String success = (String)(pi.GetValue(result, null));
Console.Write(success);
}
catch (Exception f) {
Console.Write(f);
}
You're deserializing it as a straight up object.. object doesn't have a property named success.
The alternative is to type a class that represents this:
class ExampleClass {
public bool success { get; set; }
public string next { get; set; }
public int amount { get; set; }
public int keys { get; set; }
public int credits { get; set; }
}
Then call it like this:
object result = JsonConvert.DeserializeObject<ExampleClass>(e.Result);
// ^^^^^^^^^^^^
// This
try{
PropertyInfo pi = result.GetType().GetProperty("success");
bool success = (bool)(pi.GetValue(result, null));
Console.Write(success); // True
}
catch (Exception f) {
Console.Write(f);
}
Or even better.. remove that altogether:
ExampleClass example = JsonConvert.DeserializeObject<ExampleClass>(e.Result);
Console.WriteLine(example.success); // True