This question already has answers here:
How do you serialize an enum array to a Json array of strings? [duplicate]
(2 answers)
Closed 6 years ago.
I'm using Json.NET to serialize an object that has an IEnumerable of an enum and DateTime. It's something like:
class Chart
{
// ...
public IEnumerable<int> YAxis { get; set; }
public IEnumerable<State> Data { get; set; }
public IEnumerable<DateTime> XAxis { get; set; }
}
But I need a custom JsonConverter to make the enum serialize as string and to change the DateTime string format.
I've tried using the JsonConverter attribute as mentioned here for enum and a custom IsoDateTimeConverter as done here:
[JsonConverter(typeof(StringEnumConverter))]
public IEnumerable<State> Data { get; set; }
[JsonConverter(typeof(MyDateTimeConverter))]
public IEnumerable<DateTime> XAxis { get; set; }
I was hoping it would work for an IEnumerable too, but unsurprisingly it doesn't:
Unable to cast object of type 'WhereSelectArrayIterator`2[System.Int32,Model.State]' to type 'System.Enum'.
Is there any way to say that the JsonConverterAttribute applies to each item and not on the enumerable itself?
Turns out that for enumerables you have to use the JsonPropertyAttribute and the ItemConverterType property as follows:
[JsonProperty(ItemConverterType = typeof(StringEnumConverter))]
public IEnumerable<State> Data { get; set; }
[JsonProperty(ItemConverterType = typeof(MyDateTimeConverter))]
public IEnumerable<DateTime> XAxis { get; set; }
This is mentioned in the documentation as:
To apply a JsonConverter to the items in a collection, use either JsonArrayAttribute, JsonDictionaryAttribute or JsonPropertyAttribute and set the ItemConverterType property to the converter type you want to use.
You might be confused with JsonArrayAttribute, but it
cannot target a property.
Related
I'm deserializing some JSON from a server which is, for the most part, simple:
{
"id": "ABC123"
"number" 1234,
"configured_perspective": "ComplexPerspective[WithOptions,Encoded]"
}
That "configured_perspective" property, however, is an unfortunate case of the server using a weirdly put-together string when a nested object would have been better.
To ease the suffering of our .NET users, I convert this into a custom class in my object model:
public class Example
{
public string id { get; set; }
public int number { get; set; }
public Perspective configured_perspective { get; set; }
}
// Note, instances of this class are immutable
public class Perspective
{
public CoreEnum base_perspective { get; }
public IEnumerable<OptionEnum> options { get; }
public Perspective(CoreEnum baseArg, IEnumerable<OptionEnum> options) { ... }
public Perspective(string stringRepresentation) {
//Parses that gross string to this nice class
}
public static implicit operator Perspective(string fromString) =>
new Perspective(fromString);
public override string ToString() =>
base_perspective + '[' + String.Join(",", options) + ']';
}
As you can see, I've put together a custom class Perspective that converts to and from the JSON string, but I can't seem to get Newtonsoft JSON to automatically convert the string to my Perspective class.
I tried getting it to call the string constructor with the [JsonConstructor] attribute, but it just calls the constructor with null, not with the string value present in the JSON.
I was under the impression (based on https://stackoverflow.com/a/34186322/529618) that JSON.NET would use implicit/explicit string conversion operators to convert a simple string in JSON to an instance of the target type when available, but it seems to ignore it, and just returns the error:
Newtonsoft.Json.JsonSerializationException: Unable to find a constructor to use for type Perspective. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path 'configured_perspective'
I'm trying to avoid resorting to writing a custom JsonConverter for my Example class - I was pretty sure there would be an out-of-the-box way to convert simple string values to a non-string property type, I just haven't found it yet.
I actually wrote out a custom serializer class before doing reading the last of your article, but I then had an idea.
What if we modified example to not serialize it to Perspective? And we were somewhat lazy about it?
public class Example
{
public string id { get; set; }
public int number { get; set; }
public string configured_perspective { get; set; }
private Perspective _configuredPespective;
[JsonIgnore]
public Perspective ConfiguredPerspective => _configuredPerspective == null ? new Perspective(configured_persective) : _configuredPerspective;
}
It's not perfect, and we hold onto the string wasting memory, but it might work for you as a work-around.
Currently I'm using the following variation on #Jlalonde's suggestion - tweaked such that the user experience doesn't change, taking advantage of the fact that JSON.NET looks for private properties as well.
public class Example
{
public string id { get; set; }
public int number { get; set; }
[JsonIgnore]
public Perspective configured_perspective { get; set; }
[DataMember(Name = "configured_perspective")]
private string configured_perspective_serialized
{
get => configured_perspective?.ToString();
set => configured_perspective = value == null ? null : new Perspective(value);
}
}
This question already has answers here:
Json.NET serializes enum as string even with default settings
(2 answers)
Closed 5 years ago.
What setting should I change to get the property value of an enum instead of its string representation when serializing an object? I have the following class.
public class ProductModel
{
public long ProductId { get; set; }
public int ContainerType { get; set; }
public SolidForm SolidForm { get; set; }
}
(for example) NOW ---> my json =
{ "ProductId" : 22222,
"ContainerType" : 1111,
"SolidForm" : "Solid"
}
but I need this after serialization. (not enum as string)
{ "ProductId" : 22222,
"ContainerType" : 1111,
"SolidForm" : 1
}
I want that all enums in my object converted to int.
this my settings of Json Serialization
JsonSerializerSettings = new JsonSerializerSettings
{
DateFormatHandling = DateFormatHandling.MicrosoftDateFormat,
Error = delegate (object sender, ErrorEventArgs args)
{
args.ErrorContext.Handled = true;
}
}
The default in Newtonsoft.Json is to serialize enums as int. Assuming you mean Newtonsoft.Json.
Is your enum decorated with the attribute [JsonConverter(typeof(StringEnumConverter))]?
This question already has answers here:
NewtonSoft add JSONIGNORE at runTime
(7 answers)
Closed 5 years ago.
I have a class of which I serialize objects to JSON using json.net. The class has some property that I usually didn't want serialized, so I marked it with JsonIgnore.
public class SomeClass
{
[JsonIgnore]
public int ID { get; set; }
public int SecondID { get; set; }
public string Name { get; set; }
}
Now, in a different context, I wish to export objects of the same class, but here I wish to also export the ID (that I have flagged to be ignored in the first context).
Is it possible to dynamically flag a property to be ignored before serializing to JSON or do I have to write a custom serializer to achieve this?
How can I achieve the desired behavior in the simplest possible way?
Here you can make a list of properties you want to ignore :
[JsonIgnore]
public List<Something> Somethings { get; set; }
//Ignore by default
public List<Something> Somethings { get; set; }
JsonConvert.SerializeObject(myObject,
Newtonsoft.Json.Formatting.None,
new JsonSerializerSettings {
NullValueHandling = NullValueHandling.Ignore
});
This question already has answers here:
Deserializing dates with dd/MM/yyyy format using Json.Net
(9 answers)
Closed 6 years ago.
I have this Json from a web api:
jsonstring ={"users":[{"id":1123,"last_update":"2016-02-28 14:53:04"}],"page":1,"pages":1}
which I want to deserialize in an object like:
public class Rootobject
{
public User[] users { get; set; }
public int page { get; set; }
public int pages { get; set; }
}
public class User
{
public int id { get; set; }
public DateTime last_update { get; set; }
}
for this I use:
var obj= JsonConvert.DeserializeObject<Rootobject>(jsonString);
the result has null for last_update.
jsonstring is a string result from WebClient.DownloadString(url); which look like above example.
How can I get the date on deserialization?
Edit:
None of the solutions from this post Deserializing dates with dd/mm/yyyy format using Json.Net help me fix my issue.
var obj = JsonConvert.DeserializeObject<Rootobject>(jsonString,
new IsoDateTimeConverter { DateTimeFormat = "yyyy-MM-dd HH:mm:ss" });
Fiddle
Change the property last_update as Nullable, Then it allows you to assign the null literal to the DateTime type. It provides another level of indirection. So use like the following:
public DateTime? last_update { get; set; }
This is for accepting The date even if it is null, you can specify the Date format While Deserializing the JSON. Use this Thread for that
"2016-02-28 14:53:04" is not a valid RFC3339 date time, and I think it can't parse it because of that.
It has to be:
2016-02-28T14:53:04
Also note that the can't be null, since DateTime is a struct. To make it nullable, make the data type DateTime? which does allow null values.
Case:
I receive a JSON string from third-party server, containing a list of objects.
e.g.
[{"foo": "bar", "someotherfield": "somevalue"}, {etc}, {etc}]
I have a C# class like,
public class MyObject
{
public string A { get; set; }
public string B { get; set; }
}
Now, I want to use JsonConvert.DeserializeObject, but so that it maps "foo" to A and so forth. How would I go about doing this?
You can use the JsonProperty attribute.
[JsonProperty("foo")]
public string A { get; set; }
You can use the JsonPropertyAttribute decorated on the property, giving it the name of the parameter it should find in the JSON message. You can also use a custom JsonConverter, if you do not wish to use an attribute.