JSON.net problem with JsonConvert.DeserializeObject - c#

I have the following code and json:
public class Labels
{
public Labels()
{}
public Label[] Label {get;set;}
}
public class Label
{
public Label()
{ }
public string Name { get; set; }
public int TorrentsInLabel { get; set; }
}
//...
Labels o = JsonConvert.DeserializeObject<Labels>(json);
//...
{"label":
[
["seq1",1]
,["seq2",2]
]}
I would like this array ["seq1","1"] to deserialize into Label object. What am I missing? Some attributes?
When I run I get exception: Expected a JsonArrayContract for type 'test_JSONNET.Label', got 'Newtonsoft.Json.Serialization.JsonObjectContract'.
tnx
gg

How can JsonConvert know that "seq1" corresponds to name and "1" corresponds to the TorrentsInLabel? Please have a look at JsonObjectAttribute, JsonPropertyAttribute, JsonArrayAttribute

By default a class serializes to a JSON object where the properties on the class become properties on the JSON object.
{
Name: "seq",
TorrentsInLabel: 1
}
You are trying to serialize it to an array which isn't how the Json.NET serializer works by default.
To get what you want you should create a JsonConverter and read and write the JSON for Label manually to be what you want it to be (an array).

Related

Serialize and deserialize Json property to two different values

I have a source JSON object that I get from a server that looks like this:
{
"Property A": .098
}
I have a C# class that I deserialize the JSON into using the following:
public class foo {
[JsonProperty("Property A")]
public decimal PropertyA{ get; set;}
}
var ret = JsonConvert.DeserializeObject<foo>(File.ReadAllText(someJsonString);
This allows me to read in a JSON file and convert it to a C# object. But now I would like to write this object out to JSON but change the format to be this:
{
"property_a":.098
}
I currently have another class that is identical and the only difference is that I change the JsonProperty field to the new desired name:
public class foo {
[JsonProperty("property_a")]
public decimal PropertyA{ get; set; }
}
Is there a way using Newtonsoft to have a JsonProperty read as a particular value but write as a different?

Unity c# jsonUtility functions arent working

Want to convert a object to a json string and back.
My object:
[Serializable]
public class Save
{
public Levels PlayerLvl { get; set; }
public int Kills { get; set; }
}
function in code:
testfunction(Save savedata) {
//(int)savedata.PlayerLvl equals 1
//savedata.Kills equals 5
string json = JsonUtility.ToJson(savedata);
debug.log(json) // json equals "{}"
}
The same happens when I get a json string and want to convert it back:
testFunction(string jsonstring) {
//jsonstring is a valid json string that equals Save object
Save savedata = JsonUtility.FromJson<Save>(jsonstring);
// savedate equals a new Save object without content
}
whats wrong here?
Edit:
Json that I get:
{
"Kills": 5,
"PlayerLvl": 1
}
Levels enum:
public enum Levels {
Level1 = 1,
Level2 = 2
}
See from Manual: JSON Serialization
Supported types
The JSON Serializer API supports any MonoBehaviour subclass, ScriptableObject subclass, or plain class or struct with the [Serializable] attribute. When you pass in an object to the standard Unity serializer for processing, the same rules and limitations apply as they do in the Inspector: Unity serializes fields only; and types like Dictionary<> are not supported.
Unity does not support passing other types directly to the API, such as primitive types or arrays. If you need to convert those, wrap them in a class or struct of some sort.
So you want to remove all {get; set;} in order to use fields not properties
[Serializable]
public class Save
{
public Levels PlayerLvl;
public int Kills;
}

How to create C# classes to deserialize a JSON string which starts and ends with square brackets

I am receiving a JSON string back from an API and want to deserialize it into C# objects but cannot get the classes correct.
I have tried creating the classes using http://json2csharp.com/ but it can't parse the JSON, however https://jsonlint.com/ says that the JSON is valid.
I also tried running JsonClassGeneratorLib but that says
Unable to cast object of type Newtonsoft.Json.Linq.JValue to Newtonsoft.Json.Linq.JObject
It seems to be an issue because the JSON is enclosed in [] square brackets. I believe this is valid but makes it into an array. I think I need an array somewhere in my class.
string Json = #"[""error"",{""code"":2,""msg"":""This API Key is invalid""}]";
var obj = JsonConvert.DeserializeObject<RootObject>(Json);
public class CodeMsg
{
[JsonProperty("code")]
public long Code { get; set; }
[JsonProperty("msg")]
public string Msg { get; set; }
}
public class Result
{
[JsonProperty("error")]
public string String { get; set; }
public CodeMsg cm { get; set; }
}
public class RootObject
{
public Result Result { get; set; }
}
I always get the error
Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'ConsoleApp1.RootObject' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array
Try this:
var obj = JsonConvert.DeserializeObject<List<Result>>(Json);
Explanation: If the JSON is an Array, the C# RootObject has to be either deriving from List/IEnumerable itself, or you deserialize it to a List/Array of the Type.
You can dump your RootObject class. If you wanted to use the RootObject type, make it derive from List. But this is not worth the hassle.
Your JSON is a heterogeneous array containing a string and an object. This will not deserialize cleanly into a strongly-typed class structure without a little help. One possible solution is to use a custom JsonConverter like this:
public class ResultConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Result);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JArray array = JArray.Load(reader);
Result result = new Result
{
String = array[0].Value<string>(),
cm = array[1].ToObject<CodeMsg>(serializer)
};
return result;
}
public override bool CanWrite
{
get { return false; }
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
Then tie the converter to your Result class with a [JsonConverter] attribute like this:
[JsonConverter(typeof(ResultConverter))]
public class Result
{
public string String { get; set; }
public CodeMsg cm { get; set; }
}
Finally, deserialize the JSON into the Result class like this:
var result = JsonConvert.DeserializeObject<Result>(Json);
Working demo: https://dotnetfiddle.net/RLpm5W
Note: You can delete the RootObject class; it is not needed here.
Just make sure, your json string must have same properties as JsonHolder class.
public class JsonHolder
{
public string Id {get;set;}
public string Name {get;set;}
public string Gender {get;set;}
}
var jsonHolderList = new JsonConvert.DeserializeObject<List<JsonHolder>>(jsonString);
var jsonHolder = jsonHolderList.Single()
You can also convert json string into c# object as dynamic object. Just make sure, your json string must have same properties as JsonHolder class.
dynamic obj= new JsonConver.DeserializeObject<List<JsonHolder>>(StrJson);

Unable to Serialize JSON to Dictionary

I have an issue with JSON serialization into a class with a dictionary property.
The whole process is a bit more complex, as an input i have a YAML file that i convert into a json using YamlDotNet and NewtonSoft like so
This is an example of the Yaml and the JSON output
some_element: '1'
should_be_dic_element:
- a: '1'
- b: '2'
{
"some_element": "1",
"should_be_dic_element": [
{
"a": "1"
},
{
"b": "2"
}
]
}
And the class
public class SomeClass
{
[JsonProperty(PropertyName = "some_element")]
public string SomeProperty { get; set; }
[JsonProperty(PropertyName = "should_be_dic_element")]
public Dictionary<string, string> Dictionary { get; set; }
}
I know the issue with Array dictionary so this are all the things I've tried.
Using Dictionary i get the following
error Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'System.Collections.Generic.Dictionary`2[System.String,System.String]' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array
Using a new class from Dictionary like so
[JsonArray]
class X : Dictionary<string, string> { }
error Value cannot be null.
Parameter name: key
Using KeyValuePair<string, string>[] / List<KeyValuePair<string, string>> the outcome is the amount of elements but with null values.
Any suggestions please ?
I think your JSON which you are attempting to de-serialize is not conforming to your class definition. Try changing the way you are generating the JSON.
For a dictionary-type structure, I would expect to see curly braces { instead of [ to begin the structure, e.g.:
{
"some_element": "1",
"should_be_dic_element": {
{
"a": "1"
},
{
"b": "2"
}
}
}
If you want to deserialize the existing JSON unchanged, try using your class definition to specify a list of dictionaries as such:
public class SomeClass
{
[JsonProperty(PropertyName = "some_element")]
public string SomeProperty { get; set; }
[JsonProperty(PropertyName = "should_be_dic_element")]
public List<Dictionary<string, string>> Dictionary { get; set; }
}

Deserialize string by class name

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);

Categories

Resources