Serializing plain values and objects with JObject.FromObject - c#

I have problem with serializing objects using Newtonsoft.JSON. I have a method which creates EventGridEvent object:
public EventGridEvent CreateEvent(object data) =>
new EventGridEvent
{
Id = Guid.NewGuid().ToString(),
EventTime = DateTime.Now,
Data = JObject.FromObject(data, JsonSerializer),
...other properties
}
When the method is called with "proper" object, everything serializes properly. The problem is if the data is a plain value i.e. integer or string. In this case I get an exception Object serialized to Integer. JObject instance expected. How to detect if object can be serialized with JObject.FromObject and if not use its plain value (without using try/catch)?

If EventGridEvent.Data can hold any type of JSON value, you should modify it to be of type JToken and use JToken.FromObject(Object, JsonSerializer), i.e.:
public class EventGridEvent
{
public JToken Data { get; set; }
// ...other properties
}
And then do
Data = JToken.FromObject(data, JsonSerializer),
A JToken
Represents an abstract JSON token.
It can be used to hold the JSON representation of any JSON type including an array, object, or primitive value. See: JSON.NET: Why Use JToken--ever?.

If you need to serialize a nullable value like an int? or string, JToken.FromObject() will throw an error. I've found that the implicit operator (called by casting) works better.
string s = null;
int? i = null;
JObject obj = new JObject();
// obj.Add(JToken.FromObject(s)); // throws exception
// obj.Add(JToken.FromObject(i)); // throws exception
obj.Add((JToken)s); // works
obj.Add((JToken)i); // works

Related

How do i deserialize a json to an object? My attemts end up with an JObject and not an object with my properties. How do i avoid this?

I want to convert something like this this {\"ref\":\"/my/path\",\"action\":\"set\",\"payload\":\"\"}
into a generic object in C#. What i tried is this
object mess1 = JObject.Parse(message);
dynamic mess2 = JsonConvert.DeserializeObject<object>(message);
dynamic mess3 = JValue.Parse(message);
The expected result would be an object with the properties ref, action and set. The actual result is an object containing the JObject
ChildrenTokens
Count
First
HasValues
Last
Next
Parent
...
these are not part of my object. What is the correct way of doing this?
The payload in this message is a string OR an arbitrary object. The payload is to be written to a database and i do not care what it contains.
JObject.Parse generates a JObject instance. You can do this a couple of ways, if you already have JObject, you can do the following:
var obj = JObject.Parse(json);
var command = obj.ToObject<Command>();
Or, you can work from the string:
var command = JsonConvert.Deserialize<Command>(json);
We generally use
this method
public static JObject JsonParsed(string Json)
{
return JObject.Parse(Json);
}
You can deserialize it into a dynamic object with:
dynamic parsed = JObject.Parse("ref\":\"/my/path\",\"action\":\"set\",\"payload\":\"\");
And access your properties like any other object:
Console.WriteLine(parsed.ref); // "/my/path/"
Console.WriteLine(parsed.action); // "set"
Console.WriteLine(parsed.payload); // "\"
By "object with my properties" you mean what's often referred as POCO.
You have to define a POCO object like so:
public class Poco
{
public string Ref { get; set; }
public string Action { get; set; }
public string Payload { get; set; }
}
Then deserialize your JSON like so:
string json = "{'ref':'/my/path','action':'set','payload':''}";
Poco myPoco = JsonConvert.DeserializeObject<Poco>(json);
Now you will have myPoco.Ref, myPoco.Action, myPoco.Payload properties populated from your JSON.

Convert Json object into custom Object

I have a massive json file that i am parsing. But I have a problem when parsing it.
There is a field in the file that looks similar:
"pageTitle": {
"en": "Some content here...."
},
I store this as a dictionary:
[JsonProperty("pageTitle")]
public Dictionary<string, string> PageTitle { get; set; }
But sometimes this field is empty, and when it is the Json.Net method
ToObject<MyCustomClass>()
Fails when trying to convert pageTitle because it appears to be an empty array and not an object. Is there a JsonPropery to make it ignore this empty array and just carry on?
If you would like to ignore the null values, then it is possible to decorate the property as follows:
[JsonProperty("pageTitle", NullValueHandling = NullValueHandling.Ignore)]
If the JSON string being parsed is an empty array [] or an invalid input, you might have to write a custom converter by extending the abstract class, JsonConverter or extending one of the inbuilt converters in Newtonsoft.Json.Converters and invoke it as:
var obj = JsonConvert.DeserializeObject<MyCustomClass>(jsonString, new CustomConverter());
OR
Handle the exception that happens during deserialization as follows:
var obj = JsonConvert.DeserializeObject<MyCustomClass>(json, new
JsonSerializerSettings
{
Error = HandleError
});
Handler:
private static void HandleError(object sender, ErrorEventArgs e)
{
// Get the error message using 'e.ErrorContext.Error.Message'
// e.ErrorContext.OriginalObject will give you the object/property that failed to deserialze
e.ErrorContext.Handled = true;
}

C# Parse/Deserialize JSON partially with Newtonsoft

I have to extract a part of json-string using .net or newtonsoft json.
JSON:
var json = "{\"method\":\"subtract\",\"parameters\":{\"minuend\":\"SOME_CUSTOM_JSON_OBJECT_DIFFERENT_FOR_EACH_METHOD\",\"subtrahend\":23}}";
C# Class:
class MyJson{
public string method { get; set; }
//public string parameters {get; set;}
public object parameters {get; set;}
}
I do not need to parse all the children of "parameters" json-object. "parameters" could be a very big object ([{obj1}...{obj1000}], objX of 1000 fields), parse which would be not performant.
I would like i.e. to pass it exactly as it is on some point, so conversion "string-C#object-string" would be redundant.
I do not want use Regexp or string transformations (string.Substring, Split and co), because of error margin, I know that all .net and newtonsoft string transformations based.
Question 1: if I define a property of type "object", how newtonsoft will handle this? (Documentation is worse than msdn, so I'm looking for the input from you, who already tried this).
static void Main(string[] args)
{
var json = "{\"method\":\"subtract\",\"parameters\":{\"minuend\":42,\"subtrahend\":23}}";
var data = JsonConvert.DeserializeObject<MyJson>(j);
// what internal representaion of data.parameters?
// How is it actually converted from json-string to an C# object (JObject/JsonObject).
}
In perfect case:
"parameters" is a string and calling
ExtractMyJson(jsonString)
gives me the json string of parameters.
Basically I need the newtonsoft version of
string ExtractMyJson(jsonString){
var p1 = jsonString.Split(",");
// .. varios string transformations
return pParams;
}
Note: please don't reference "dynamic" keyword or ask why no string transformations, it's the very specific question.
If you know that your parameters are unique you can do something like this:
class MyJson
{
public string method { get; set; }
public Dictionary<string,object> parameters { get; set; }
}
................
string json = "{\"method\":\"subtract\",\"parameters\":{\"minuend\":{\"img\": 3, \"real\": 4},\"subtrahend\":23}}";
var data = JsonConvert.DeserializeObject<MyJson>(json);
If you let it as object is going to receive the type Newtonsoft.Json.Linq.JObject.
Have you tried JTOKEN?
It is a rather simple solution to partially read basic or nested JSONs as described in this post.
For a nested JSON
{
"key1": {
"key11": "value11",
"key12": "value12"
}
"key2": "value2"
}
it would look like this
JToken token = JToken.Parse(json);
var value12 = token.SelectToken("key1.key12");
to get the element of the key "key12.
I think this could go nicely with your problem.
Well Objects are treated the same way your parent object is treated. It will start from the base of the graph. So if you have something like:
Person
{
Address Address {get;set;}
}
The Json will start Deserializing Address and then add in the Person object.
If you want to limit thesize of the graph depth you can use a setting like :
JsonConvert.DeserializeObject<List<IList<IList<string>>>>(json, new JsonSerializerSettings
{
MaxDepth = 2
});
For more configurations of the JsonSerializer check JsonSerializerSettings
If your field is an object then that object will have the KeyValuePair of every property that it holds, based on that when you cast that field you can access that type.(the behaviour is the same as assigning a type to an object in C#).
Update: So if you question using JsonObject or type, well JObject is and intermediary way to construct the json format in a generic format. But using the Type deserializatin means you can ignore properties you are not interested in. Mapping to a json with a type makes more sense because it creates a new object and dismisses the old JObject.

Using ServiceStack's JsonSerializer to serialize arrays containing some null items

In ServiceStack 3.9, when deserializing a JSON array that contains some nulls, the null values are deserialized as nulls, as I expected. However, when I then serialize the same array back to JSON again, the nulls turn into empty objects.
public class MyClass
{
public string Foo { get; set; }
}
[Fact]
public void Test()
{
var originalJson = "[{\"Foo\":\"Bar\"},null]";
var arr = ServiceStack.Text.JsonSerializer.DeserializeFromString<MyClass[]>(originalJson);
var result = ServiceStack.Text.JsonSerializer.SerializeToString(arr);
// output is actually: [{"Foo":"Bar"},{}]
Assert.Equal(originalJson, result); // fails
}
Is this expected behavior? Or is there another way to serialize an array containing some nulls, and have the null items appear in JSON as nulls rather than as empty objects?
Note that when serializing an array of literals, like strings, null values are returned as null values, and not as objects.
I had this problem too. I found that if the array is cast to object[] before calling SerializeToString() then the null values are output as expected.
var result = ServiceStack.Text.JsonSerializer.SerializeToString((object[])arr);
// result is correct [{"Foo":"Bar"}, null]
You can globally set the serialization of MyClass using this JsConfig:
JsConfig<MyClass[]>.RawSerializeFn = (obj) => ((object[])obj).ToJson();

Determining object "type" during json deserialization

While trying to de-serialize a complex JSON object (JIRA issue) into an object containing a dictionary of type string-Field I've hit a bit of a bump.
While I can de-serialize various pre-determined object types (standard), I'm having a bit of a harder time with the custom fields, which could be of various types (they all begin with customfield_ followed by a set of numbers).
The custom fields can be floats, strings, booleans, objects and arrays of objects. The latter of these is causing me issues since I can't seem to determine what the object is before I de-serialize it.
I've searched for a way to perhaps "peek" at the data in the object before de-serializing as one of the fields contains information specific to it's type. This is all so I can determine the type of the object and tell Json.Net what to de-serialize it as.
I've considered parsing the JSON string before serialization to get the information, or maybe just when hitting this particular case, but maybe there is a better way?
Thanks in advance for any advice on this.
You can deserialize to an object with Json.Net. Here's a quick and dirty example:
using System;
using Newtonsoft.Json;
namespace Sandbox
{
class Program
{
private static void Main(string[] args)
{
var nestDto = new Dto
{
customfield_1 = 20,
customfield_2 = "Test2"
};
var dto = new Dto
{
customfield_1 = 10,
customfield_3 = new[] { nestDto },
customfield_2 = "Test"
};
var jsonString = JsonConvert.SerializeObject(dto);
Console.WriteLine(jsonString);
var fromJsonString = JsonConvert.DeserializeObject<Dto>(jsonString);
Console.WriteLine(fromJsonString.customfield_3[0].customfield_2); //Outputs Test2
Console.ReadKey();
}
}
class Dto
{
public int customfield_1 { get; set; }
public string customfield_2 { get; set; }
public Dto[] customfield_3 { get; set; }
}
}
Instead of peaking, you can deserialize as the same type as JSON.net uses for ExtensionData explicitly. For example:
if (reader.TokenType == JsonToken.StartArray)
{
var values = serializer.Deserialize<List<Dictionary<string, JToken>>>(reader);
objectContainer = ClassifyAndReturn(values);
}
private ObjectType ClassifyAndReturn(List<Dictionary<string, JToken>> values)
{
if (values.First().ContainsKey("self"))
{
string self = values.First()["self"].Value<string>();
if (self.Contains("customFieldOption"))
//... Then go into a series of if else cases to determine the object.
The representation of the objects are given as a Dictionary of string to JToken, which can then easily be checked and assigned manually or in some cases automatically deserialized (in the case one of the fields is another object).
Here is what an object constructor could look like:
internal myobject(Dictionary<string, JToken> source)
{
Self = source["self"].Value<string>();
Id = source["id"].Value<string>();
Value = source["value"].Value<string>();
}

Categories