Serialize and deserialize Json property to two different values - c#

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?

Related

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

Custom JSON serialization/deserialization to read property in multiple possible formats

My application reads JSON files created using a format like this:
{
"myProperty": {complex JSON here}
}
class MyClass
{
public MyChildClass MyProperty {get; set;}
}
I need to change the way the class works, so that it looks like this instead:
class MyClass
{
public MyNewChildClass MyNewProperty {get; set;}
}
and I need to be able to support files created in the older format, but also support a file if it was created using the new format.
I have the code to convert a MyChildClass object into a MyNewChildClass object, but how can I set up the serialization so that the object can deserialize the old format, changing the property name and type from MyChildClass MyProperty to MyNewChildClass MyNewProperty AND just use the new format when serializing AND deserialize using the new format if that is what the JSON file contains?
If you use both properties, the json will work for both, new and old.
class MyClass
{
[JsonPropert("myProperty")]
public MyChildClass MyProperty {get; set;}
[JsonProperty("myNewProperty")] // -> Remember, case matters.
public MyNewChildClass MyNewProperty {get; set;}
}
When you deserialize the class, add a check to see which is not null and work with that (different methods for each i guess). This should help you keep the breaking change to a minimum.
BTW>. if you have the code that converts the new to the old or vice versa, you can check if the value of old is null, then run that process/method you have to convert new to old and continue on with the object. Remember, it would have to be After the deserialization,
var properties = JsonConvert.DeserializeObject<MyClass>("data");
if (properties.MyNewProperty == null)
{
properties = myMethodToConvertOldToNew(properties);
}
public MyClass myMethodToConvertOldToNew(MyClass)
{
if (properties.New == null)
{
properties.New = ConversionMethod(properties.Old, properties.New);
// dont have to, but,
properties.Old = null;
}
return properties.
}
Why not add a private property to your class that will set your new property:
class MyClass
{
[JsonProperty]
private MyChildClass MyProperty { set => MyNewProperty = YourConversionMethod(value); }
public MyNewChildClass MyNewProperty { get; set; }
}
The JsonProperty attribute will ensure that the private setter is used.

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

Deserialize json Object using newtonsoft json

I have a json like
{"NewMessage":[{"Id":-1,"Message":"Test","MessageName":"test1"}],"OldMessage":[]}
and I need to deserialize this json in to my class object.
My Class
public class NewMessage{
public int Id{get;set;}
public string Message{get;set;}
public string MessageName{get;set;}
}
public class OldMessage{
public int Id{get;set;}
public string Message{get;set;}
public string MessageName{get;set;}
}
how can we achive this by using newtonsoft.json. can anyone help. thanks in advance
Your JSON actually contain an object which have properties of your defined classes - given the code posted, you don't have a class to deserialize into.
The first thing you can do is obvious - create a third class - MessagePair - which declares two properties - NewMessage[] and OldMessage[]. Then you can deserialize the JSON string like this:
var theMessages = JsonConvert.DeserializeObject<MessagePair>(jsonText);
If you don't like to create separate class, you can then deserialize into anonymous object like this:
var theMessages = new {
NewMessage[] NewMessages = null,
OldMessage[] OldMessages = null
};
theMessages = JsonConvert.DeserializeAnonymousType(jsonText, theMessages);

JSON.net problem with JsonConvert.DeserializeObject

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

Categories

Resources