Handling deserialization error - c#

I have class to deserialize from json
class SeeSharp
{
public int Number;
}
Good json is smth like
{Number:1}
Wrong json which comes from PHP is
{Number:false}
I use following way to handle deserialization error http://blog.mrlacey.co.uk/2012/03/debugging-deserialization-errors-in.html
When fails reading member of type string/int/double/bool/etc, I would like to set it's value to default of this type and mark that error as handled.
Currently, JsonSerializationSettings.Error delegate doesn't allow to set value to failed member and doesn't show any information about type of member failed.
If there is an option to do that in another way, would be great to know it.

Can you use this class?
public class SeeSharp
{
public string Number
{
get
{
return _number.ToString();
}
set
{
if (!int.TryParse(value, out _number))
_number = default(int);
}
}
public int _Number { get; set; }
}
JsonConvert will use the string property Number to set data, which handles the parsing itself. And then use the property _Number in your code as int

Related

C# 9 require property set at construction without explicit constructor [duplicate]

I have requirement in a custom class where I want to make one of my properties required.
How can I make the following property required?
public string DocumentType
{
get
{
return _documentType;
}
set
{
_documentType = value;
}
}
If you mean "the user must specify a value", then force it via the constructor:
public YourType(string documentType) {
DocumentType = documentType; // TODO validation; can it be null? blank?
}
public string DocumentType {get;private set;}
Now you can't create an instance without specifying the document type, and it can't be removed after that time. You could also allow the set but validate:
public YourType(string documentType) {
DocumentType = documentType;
}
private string documentType;
public string DocumentType {
get { return documentType; }
set {
// TODO: validate
documentType = value;
}
}
.NET 7 or newer
Syntax
public class MyClass
{
public required string Name { get; init; }
}
new MyClass(); // illegal
new MyClass { Name = "Me" }; // works fine
Remarks
The required properties must declare a setter (either init or set).
Access modifiers on properties or setters cannot be less visible than their containing type, as they would make impossible to initialize the class in some cases.
public class MyClass
{
internal required string Name { get; set; } // illegal
}
Documentation
Official documentation here
Feature demo here
.NET 6 or older
See this answer
If you mean you want it always to have been given a value by the client code, then your best bet is to require it as a parameter in the constructor:
class SomeClass
{
private string _documentType;
public string DocumentType
{
get
{
return _documentType;
}
set
{
_documentType = value;
}
}
public SomeClass(string documentType)
{
DocumentType = documentType;
}
}
You can do your validation – if you need it – either in the property's set accessor body or in the constructor.
With the release of .NET 7 and C# 11 in November 2022 you can now use the required modifier this way:
public class Person
{
public Person() { }
[SetsRequiredMembers]
public Person(string firstName) => FirstName = firstName;
public required string FirstName { get; init; }
public int Age { get; set; }
}
And when you don't have the required properties it will throw an error when you try to initialize an object.
For more information refer to:
https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#required-members
https://learn.microsoft.com/en-us/dotnet/csharp/properties#init-only
Add a required attribute to the property
Required(ErrorMessage = "DocumentTypeis required.")]
public string DocumentType
{
get
{
return _documentType;
}
set
{
_documentType = value;
}
}
For custom attribute detail Click Here
I used an other solution, not exactly what you want, but worked for me fine because I declare the object first and based on specific situation I have different values. I didnt want to use the constructor because I then had to use dummy data.
My solution was to create Private Sets on the class (public get) and you can only set the values on the object by methods. For example:
public void SetObject(string mandatory, string mandatory2, string optional = "", string optional2 = "")
This one liner works in C# 9:
public record Document(string DocumentType);
new Document(); // compiler error
new Document("csv"); // correct way to construct with required parameter
This explains how it works. In the above code, Document is the name of the class or "record". That first line of code actually defines an entire class. In addition to this solution essentially making a required DocumentType property (required by an auto implemented constructor), because it uses records, there are additional implications. So this may not always be an appropriate solution, and the C# 11 required keyword will still come in handy at times. Just using record types doesn't automatically make properties required. The above code is a special syntax way of using records that essentially has this effect as well as making the property init only and causes a deconstructor to be automatically implemented.
A better example would be using an int property instead of a string since a string could still be empty. Unfortunately I don't know of any good way to do extra validation within the record to make sure the string is not empty or an int is in range, etc. You would have to go deeper down the TOP (type driven development) rabbit hole, which may not be a bad thing. You could create your own type that doesn't allow empty strings or integers outside your accepted range. Unfortunately such an approach would lead to runtime discovery of invalid input instead of compile time. There might be a better way using static analysis and metadata, but I've been away from C# for too long to know anything about that.

Custom Attribute to read the value and property

I trying to create a custom Attribute to read a property and a value, here is the code, anyone knows how I can do this?
private string reason;
[CustomAttribute]
public string Reason
{
get
{
return reason;
}
set
{
// Read the reason and the value to the attribute
reason = value;
}
}

Parsing within a Set method

I know this might be a simple question but I was wondering in C# what is the best way to parse an incoming string within a set method to an int e.g. if I have
public int foo {get; set;}
On the set I want to parse a incoming string
There are a lot of ways to skin this cat. This is how I would do it.
Let's say your property is:
public int Foo
{
get { return _foo; }
set { _foo = value; }
}
You could do is add a helper method on your class:
public void SetFoo(string sFoo)
{
Foo = Convert.ToInt32(sFoo);
}
Then, when you need to set the value using a string, you can call that method:
myFooObject.SetFoo("4");
I guess you have some string and you want to parse it into int by setter. Of course, you can do it, but the property must be string.
private int foo
public string Foo
{
get
{
return foo.ToString();
}
set
{
foo = Int32.Parse(value);
}
}
But remember that Int32.Parse() throws an exception if your string is not a number. You should consider using Int32.TryParse() which could be a better choice in this case.
Do you mean this?
private int _foo;
public int Foo
{
get { return _foo; }
set
{
_foo = value;
ParseFoo(_foo);
}
}
but since you're talking about strings...
private string _foo;
public string Foo
{
get { return _foo; }
set {
_foo = value;
ParseIncomingString(_foo);
}
}
Well since the property is of type int, it's not possible to assign a string to it. So you need to do this parsing before assigning the value to your property.
Alternatively you could make your setter private, and have a public method that takes string, and do your validation inside of the method set the property if validation succeeds.
I would recommend you to make sure that your value is an int before you set it to your property when the set method is called automatically. This means that the string you want to set to your property should be parsed before it's set.
If you want to do it as you asked then you could simply use the Int32.Parse(value) or Int32.TryParse(value).
The difference between those two is that Parse(value) method throws an exception if the the parsing fails which means that you have to use try-catch block if you want to catch the exception and where TryParse(value) returns false if the parsing fails and true on success.
You can read more at: https://msdn.microsoft.com/en-us/library/bb397679.aspx

c# property setter body without declaring a class-level property variable

Do I need to declare a class-level variable to hold a property, or can I just refer to self.{propertyname} in the getter/setter?
In other words, can I do this? (where I haven't defined mongoFormId anywhere):
public string mongoFormId
{
get
{
return this.mongoFormId;
}
set
{
this.mongoFormId = value;
revalidateTransformation();
}
}
You can either use automatic accessors or implement your own. If you use automatic accessors, the C# compiler will generate a backing field for you, but if you implement your own you must manually provide a backing field (or handle the value some other way).
private string _mongoFormId;
public string mongoFormId
{
get { return this._mongoFormId; }
set
{
this._mongoFormId = value;
revalidateTransformation();
}
}
UPDATE: Since this question was asked, C# 6.0 has been released. However, even with the new syntax options, there is still no way to provide a custom setter body without the need to explicitly declare a backing field.
You need to set a field variable and store the value there, if you're going to use custom getter and setter.
With the code you have right now you will be running into a stack overflow exception. When you assign something to mongoFormId, you'll execute the line this.MongoFormId = value;. This is an assignment to mongoFormId, resulting in executing the line this.MongoFormId = value;, and so on. It won't ever stop.
The correct way is a field:
private string _mongoFormId;
public string mongoFormId {
get { return this._mongoFormId; }
set {
this._mongoFormId = value;
revalidateTransformation();
}
}
You should have a backing variable. Take a closer look:
get { return this.mongoFormId; }
Is going to call the getter on mongoFormId, which will call that code again, and again, and again! Defining a backing variable will avoid the infinite recursive call.
Check MSDN Properties Overview
While a property definition generally includes a private data member,
this is not required. The get accessor could return a value without
accessing a private data member. One example is a property whose get
method returns the system time. Properties enable data hiding, the
accessor methods hide the implementation of the property.
You can do it both the ways.
If you want to have a class level member variable then do it this way -
public class sampleClass
{
private string _mongoFormId;
public string mongoFormId {
get { return _mongoFormId; }
set {
_mongoFormId = value;
revalidateTransformation();
}
}
}
Or do this simple in class, if no need for revalidateTransformation() execution call there
public class sampleClass
{
public string mongoFormId {get; set;}
}
This won't work since you get a recursive call to the property.
If I'm not mistaken, the result will be a StackOverflowException.
You must use a variable.
private string mongoFormId;
public string MongoFormId
{
get
{
return this.mongoFormId;
}
set
{
this.mongoFormId = value;
revalidateTransformation();
}
}
If you don't have to execute revalidateTransformation, you can use the auto-property.
This will create a backingfiled for you behind the scene.
public string MongoFormId { get; set; }
With the code you wrote, you are creating a recursive endless loop on both the get and set. The this keyword refer to the current class, not the property you are in.
So yes, you need to declare a private field. And to avoid confusion, create properties following the MSDN Naming Guideline (Use Pascal case for properties, camel case for private fields). And please do the same for your methods, it should be RevalidateTransformation instead of revalidateTransformation if you follow the C# convention instead of java's.
private string mongoFormId;
public string MongoFormId
{
get
{
return mongoFormId;
}
set
{
mongoFormId = value;
RevalidateTransformation();
}
}
public string mongoFormId {
get {
return this.mongoFormId;
}
set {
this.mongoFormId = value;
revalidateTransformation();
}
}
this way you have the Function recursive on all paths
The only way i see is to use a private data member. As other boys tells.

Read XML with C# with custom deserializer

I'm trying to deserialize a piece of XML offered by some API. However this API is dumb, for example, a bool is not true, but True. And having an element
[XmlElement("Foo")]
public bool Foo { get;set; }
and then the matching XML:
<...><Foo>True</Foo></...>
does NOT work, because True is not a valid representation of bool (the API is written in Python, which is, I think, more forgiving).
Is there any way to put some attribute on my property Foo to say to the system: when you encounter this element, put it through this converter class?
Edit:
The XML is large, and most of them are stupid, not directly convertible objects, like 234KB, which I need to parse to the exact value.
Do I need to write a wrapper property for each of them?
You could use a backing property:
public class MyModel
{
[XmlIgnore]
public bool Foo
{
get
{
return string.Equals(FooXml, "true", StringComparison.OrdinalIgnoreCase);
}
set
{
FooXml = value.ToString();
}
}
[XmlElement("Foo")]
public string FooXml { get; set; }
}

Categories