This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Using Json.net - partial custom serialization of a c# object
I have a class that I successfully get to serialize in json.net when using asp.net MVC 4 WebAPI. The class has a property that is a list of strings.
public class FruitBasket {
[DataMember]
public List<string> FruitList { get; set; }
public int FruitCount {
get {
return FruitList.Count();
}
}
}
In my Get method the serialization happens ok and I get an empty array i.e. [] for the FruitList property in my JSON. If I use the same json in a PUT request's body I get an error in the FruitCount property during deserialization because FruitList is null.
I want the FruitList property (basically my get only properties) to serialize but not deserialize. Is it possible with a setting or other wise with json.net?
I realize this does not answer your question, but addresses the error being generated so might make worrying about custom serialization irrelevant
use a private variable for FruitList, return it in the get and in set, if value is null then set the private variable equal to a new list.
public class FruitBasket
{
private List<string> _fruitList;
[DataMember]
public List<string> FruitList
{
get
{
return _fruitList;
}
set
{
if (value == null)
{
_fruitList = new List<string>();
}
else
{
_fruitList = value;
}
}
}
public int FruitCount
{
get
{
return FruitList.Count();
}
}
}
Related
This question already has answers here:
How to ignore JsonProperty(PropertyName = "someName") when serializing json?
(2 answers)
Closed 3 years ago.
I have a backend-service that calls a REST-Api. The result of that API is then deserialized into my entity:
public class Item {
[JsonProperty("pkID")]
public int Id {get;set;}
}
JsonConvert.DeserializeObject<Item>(responseString);
This works fine. But I also want to return the result as a JSON-string so I can use it from the Frontend. When now Serializing my object of Type "Item" using JsonConvert.SerializeObject(item) I want to return something like
{ Id: 1 }
Instead on serializing it also uses the JsonProperty and returns
{ pkID: 1 }
instead.
How can I tell the serializer to ignore the JsonProperty on serializing, but use it on deserializing?
I am NOT searching for a way whether the property should be serialized or not, but whether the propertyName should be used or the the name from the JsonProperty on serializing.
You could use a set-only property that points to the 'good' property.
public class Item
{
public int Id { get; set; }
[JsonProperty("pkID")]
public int BackwardCompatibleId { set => Id = value; }
}
// test
var x = new Item { Id = 88 };
var json = JsonConvert.SerializeObject(x); // {"Id":88}
var clone = JsonConvert.DeserializeObject<Item>("{\"pkId\":99}");
you could use an own implementation of the ContractResolver.
here is an answer that could probably work: https://stackoverflow.com/a/20639697/5018895
This question already has answers here:
running a transformation on a Json DeserializeObject for a property
(2 answers)
Closed 3 years ago.
I have the following JSON:
{
"lastOcurrences":[
{
"myString":"16726354"
},
{
"myString":"66728744"
},
{
"myString":"91135422"
}
]
}
and I have a class to deserialize it on:
public class JsonObject
{
public List<LastOcurrence> LastOcurrences { get; set; }
}
public class LastOcurrence
{
public string MyString { get; set; }
}
Upon deserializing it with JsonConvert.DeserializeObject<T>(json), I'd like to be able to format the string myString, to store 167-263-54, instead of 16726354.
What solution would please my soul: Using attributes on the properties, something of the likes of JsonConverter, but...
What i'd like to avoid doing: I would not like to use reflection to iterate through every property, only to then read the attribute and apply the formatting. Is there any way of doing this 'automatically' with JsonConvert?
One possible solution is to use custom getters and setters for this and when it is deserialized you keep the raw data stored. This will do JIT formatting. Depending on the usage of this data this could be much quicker however if there are a lot of repeated reads of the same data then this may be a bit slower.
public class LastOcurrence
{
private string _myString;
public string MyString
{
get { return Regex.Replace(_myString, #"^(.{ 3})(.{ 3})(.{ 2})$", "$1-$2-$3"); }
set { _myString = value; }
}
}
I am receiving JSON messages that are matched to the following class:
public class Response
{
public int Code { get; }
public string Message { get; }
public string Result { get; }
}
But the value of Result property depends on what we get in Code and does not have a fixed structure.
E.g. if Code = 1, Result will return a list of objects of type X and if Code = 2, Result will return a list of objects of type Y.
When I try to deserialize a message I am receiving, having Result type set to string does not seem to work.
var responseObj = JsonConvert.DeserializeObject<Response>(response);
if (responseObj.Code == 1)
{
return responseObj.Result;
}
The return statement above throws the following exception:
Unexpected character encountered while parsing value: [. Path 'Result'
How can I define my class so that it receives the entire text of Result and I can decide about its deserialization later? Because all my requests respond to with the above structure and I'd like to manage all these requests from the same place.
How can I define my class so that it receives the entire text of Result and I can decide about its deserialization later?
If that is what you want to do then make your Result property a JToken instead of a string as shown below. You will also need to add setters to all of the properties shown in your Response class to allow the deserialization to work properly: you can't deserialize into read-only properties.
public class Response
{
public int Code { get; set; }
public string Message { get; set; }
public JToken Result { get; set; }
}
Once you know what type the Result should be converted into, you can use the ToObject() method to do that. For example:
Response responseObj = JsonConvert.DeserializeObject<Response>(response);
if (responseObj.Code == 1)
{
var listOfX = responseObj.Result.ToObject<List<X>>();
...
}
Fiddle: https://dotnetfiddle.net/pz5m63
This question already has answers here:
How do I get json.net to serialize members of a class deriving from List<T>?
(3 answers)
Closed 5 years ago.
Consider the following program: (.NET Fiddle Link)
public class Program
{
public static void Main()
{
var carsa = new ListOfCarsA();
carsa.Cars.Add("Toyota");
carsa.Cars.Add("Lexus");
Console.WriteLine(JsonConvert.SerializeObject(carsa, Formatting.Indented));
var carsb = new ListOfCarsB();
carsb.Add("Nissan");
carsb.Add("Infiniti");
Console.WriteLine(JsonConvert.SerializeObject(carsb, Formatting.Indented));
}
}
public class ListOfCarsA
{
public string CollectionName { get { return "CarsA"; } }
public List<string> Cars { get; set; }
public ListOfCarsA()
{
Cars = new List<string>();
}
}
public class ListOfCarsB : List<string>
{
public string CollectionName { get { return "CarsB"; } }
}
This then outputs the following:
{
"CollectionName": "CarsA",
"Cars": [
"Toyota",
"Lexus"
]
}
And
[
"Nissan",
"Infiniti"
]
Why does the property CollectionName not get serialised and output CarsB, but the same property on the ListOfCarsA results in CarsA being serialised?
What is the solution to this problem - How could I have a class similar to ListOfCarsB but still have any extra members serialised? I have tried using the attributes [JsonProperty("CollectionName"] and [JsonRequired] but these seem to do nothing.
This is because your second example IS a list, whilst the first example only contains one. Json.Net knows how to create json from lists and so is ignoring the rest of your custom code. Not much you can do about this except write a custom formatter
I would like to deserialize my Json in two step because I have to read the first part to know what kind of Object it is.
I have to read this kind of Json :
{"header":3,"data":{"result":"myResult"}}
it's more readable like that
{
"header":3,
"data":{
"result":"myResult"
}
}
I deserialize this Json in a class named ProtocolHeader :
public class ProtocolHeader
{
[JsonProperty("header")]
public int Header { get; set; }
[JsonProperty("data")]
public string Data { get; set; }
}
To do this I use this code :
JsonConvert.DeserializeObject<ProtocolHeader>(Json)
Depending on the value of the Header, I will choose different class to deserialize the end of the file.
For example, I could have another class
public class ProtocolResult
{
[JsonProperty("result")]
public string Result{ get; set; }
}
or like that
public class ProtocolError
{
[JsonProperty("errorNumber")]
public int ErrorNumber{ get; set; }
[JsonProperty("additionalInformation")]
public string AdditionalInformation{ get; set; }
}
Do you have an idea to seperate the Deserialize Object in two steps ?
Thanks
You could make 3 classes.
One common class (not base) which has all of the fields, then a ProtocolResult & ProtocolError
Then implement an implicit cast to each.
You could also put a IsError getter on to your common class to decide how to use it.
You can use a reader to only read as long as you need, then skip out of the reader and do your real deserialization.
Probably not a whole lot better than deserializing into a simple object first then a real object later, but it's an alternative.
You can probably tweak this a bit.
string json = #"{""header"":3,""data"":{""result"":""myResult""}}";
using (var stringReader = new StringReader(json))
{
using (var jsonReader = new JsonTextReader(stringReader))
{
while (jsonReader.Read())
{
if (jsonReader.TokenType == JsonToken.PropertyName
&& jsonReader.Value != null
&& jsonReader.Value.ToString() == "header")
{
jsonReader.Read();
int header = Convert.ToInt32(jsonReader.Value);
switch (header)
{
case 1:
// Deserialize as type 1
break;
case 2:
// Deserialize as type 2
break;
case 3:
// Deserialize as type 3
break;
}
break;
}
}
}
}
Option 1: Without using an abstract base class for your data classes.
The easiest I've found to do this is as follows:
Declare your class using JToken as the field type for the unknown object.
[JsonObject(MemberSerialization.OptIn)]
public class ProtocolHeader
{
[JsonProperty("header")]
private int _header;
[JsonProperty("data")]
private JToken _data;
}
Expose the specialized data in properties.
public ProtocolResult Result
{
get
{
if (_data == null || _header != ResultHeaderValue)
return null;
return _data.ToObject<ProtocolResult>();
}
}
public ProtocolError Error
{
get
{
if (_data == null || _header != ErrorHeaderValue)
return null;
return _data.ToObject<ProtocolError>();
}
}
Option 2: With using an abstract base class for your data classes.
Another option is to create an abstract base class for the various data types, and create a static method in the abstract base class to perform the type selection and proper deserialization. This is particularly useful when the type information is contained in the object itself (e.g. if header was a property inside the data object).
The LoadBalancerConfiguration<T>._healthMonitor field has the type JObject, but the HealthMonitor property in the same class returns a HealthMonitor object.
The HealthMonitor.FromJObject method performs the actual deserialization.