How to detect Json property sent twice - c#

Given json:
{ "x":"a", "x":"b" }
When deserializing into a C# dynamic object, an object is created with property x with value b. No JsonReaderException is thrown, even though the same property is sent twice.
Is there a way to detect if property is sent more than once in the json string?

The reason why no JsonReaderException is thrown is because duplicate keys are valid in JSON.
A quick and dirty workaround would be to have a counter that gets incremented every time X property on your class gets set. If it is > 1 then you know.
public class Test
{
private string _x;
private int xCounter = 0;
public string X
{
set
{
if(xCounter > 1) throw new Exception("DUPES");
xCounter++;
_x = value;
}
get
{
return _x;
}
}
}
This will obviously fail if you try to set X again after deserialization.

Related

How get set property works in C#?

I am new to C# and am exploring the very basic of C# get and set properties. What I have found is, The get set accessor or modifier mostly used for storing and retrieving value from the private field.
In this case, What is the problem with using public fields?
Another thing, I have written some conditions inside get and set. The code is
public int Number
{
get
{
if(Number>10)return 10;
else
{
return Number;
}
}
set
{
if (value > 10)
{
Number = 10;
}
else
{
Number = value;
}
}
}
Whats the problem here?
And another interesting thing is, in VS, the recursive sign appears where I check the conditions.Can someone explain it, please?
I am new to C# and wants to learn from the basic.
Thanks in advance.
Initial Problem - StackOverflow
The problem is that you are inadvertently using recursion, which is going to lead to a stack overflow, because your getters and setters for the Number property are getting and setting the Number property, rather than a backing field.
It should at the very least be changed to this:
private int number;
public int Number
{
get
{
if(this.number>10)return 10;
else
{
return this.number;
}
}
set
{
if (value > 10)
{
this.number = 10;
}
else
{
this.number = value;
}
}
}
You are missing a private backing field. Your property is self-referencing (hence the recursion symbol).
Try this instead:
private int _number;
public int Number
{
get
{
if(_number > 10)
{
return 10;
}
else
{
return _number;
}
}
set
{
if (value > 10)
{
_number = 10;
}
else
{
_number = value;
}
}
}
As far as I can tell you are calling the Number several times inside your code.
And the recursive loop will run forever until it runs into a StackOverflow :)
I ran your code with :
this.Number = 100;
int num = this.Number;
Basically this should trigger the setter and the getter. When the if clause is setting the number to 10, the first recursion is entered since you are setting the number again. It will try to set the number to 10 recursively by Number=10
Add a backing field above number, like this:
private int number; // Backing field
public int Number
{
get { return number; } // Getter
set { number = value; } // Setter
}
The main idea of a property with public read/write access is to simply be a mutator and accessor for the internal state of their containing object.
When you have conditional logic inside these get/set methods their "contract" with consumers of the class is being broken....when I call the accessor/getter
var number = anInstance.Number;
...I expect to receive the current state of the anInstance object's number, not some logic-driven derivative of it. Similarly for the Mutator/setter
anInstance.Number = 123;
...I expect that to automatically set the internal state of the anInstance object's number.
If i set the Number in one statement...
anInstance.Number = 123; // I expect anInstance to have an internal state of 123 for it's Number
var x = anInstance.Number; // I expect 123 back, not 10
...if I then retrieve that value on the next line, I expect the same value back, but with your current implementation (if it wasn't also recursive - see below), when I set Number to 123, this is being ignored and the value of 10 is saved as the new internal state and when I then retrieve Number I would get back a value of 10.
It is not the concern of the Number property to be changing what the caller has requested be set as it's value. An invoker of the Number property rightly expects it's instructions to be followed and the invoker shouldn't have to know about weird internal getter-setter logic in order to function.
If you really need to get/set things in a conditional way, the place for the conditional logic is outside the class containing the Number property, i.e. replace the Number property with a simple auto-implement getter-setter and use in the following way.
int x = anInstance.Number > 10 ? 10 : anInstance.Number; // replaced getter logic outside the class containing the `Number` property
anInstance.Number = x > 10 ? 10 : x; // replaced setter logic
As for the reason why you are seeing the recursion symbol, that is because your code is recursively calling itself. The Number property is calling itself, instead of some backing field. Change the property to be like...
private int number;
public int Number
{
get
{
return number; // note the lower-case 'n' refers to the private field instead of the property
}
set
{
number = value;
}
}
Note, though, that there is no need to have a private backing field when you use your property in this simple way. If the intent is to have full read-write access, you could simply use a public field.
public int Number;
However, a property allows you to control access to fields, e.g.
public int Number { get; private set; }
which a simple public property does not allow, although you can use the readonly modifier to give this behaviour.
public readonly int Number;
However, another advantage of using a property over using a field is that it can offer greater control over how internal state is used/stored, e.g.this example is taken from MSDN
class TimePeriod
{
private double seconds;
public double Hours
{
get { return seconds / 3600; }
set { seconds = value * 3600; }
}
}
In this example, the caller of this class' Hours property is getting and setting a value of hours but under the hood the internal state of the class is storing/retrieving using seconds. This would not be possible with a public field.

Intercept a setter in C# [duplicate]

This question already has answers here:
c#: getter/setter
(9 answers)
Closed 7 years ago.
I'm trying to learn C#, and am coming from Java. I've seen this in C#:
class A {
public string x { get; set; }
}
What do I do if I want to intercept the incoming value on the setter?
This is just syntactic sugar for
private string x;
public string X
{
get { return this.x; }
set { this.x = value; }
}
which is effectively what the compiler really outputs for your code, though you can't access the field x directly.
Always use this long form if you need to do anything beyond setting and retrieving the value from a field.
You can create a backing store:
private string _x;
public string x {
get {
return _x;
}
set {
// do something - you can even return, if you don't want the value to be stored
// this will store the value
_x = value;
// do something else
}
}
First you should make a private property that you will store the actual values in. In the get function just return that private property. In the set method you can use the value keyword to see the incoming value and do whatever you want before actually setting the private property;
public class A
{
private string xPrivate;
public string X {
get { return this.xPrivate; }
set { this.xPrivate = value; }}
}

(Duplicated) Difference between 'public int x;' and 'public int x { get; set; }

What is the difference, if any, between
public int x;
and
public int x { get; set; }
?
The first one is called a field. The second one is a property, in this case an auto-implemented property.
Properties act like fields but use a getter and a setter function to retrive and set the value. Another way of writing the above property is as follows:
private int _x;
public int X
{
get
{
return _x;
}
set
{
_x = value;
}
}
The variable _x in this case is called a backing field. With an auto-implemented property you can't access the backing field or customize code in the getter/setter, but if you don't need to than it's shorter and more succinct.
As a rule in C# most of the time any public member should be exposed as a property instead of a field.
The difference between thise two is that a property can do something more than just get / set a variable.
take this example:
private int _x;
public int x
{
get
{
//do something
return _x;
}
set
{
if(_x != value)
PropertyChanged("x");
_X = value;
}
}
when we set the property - we notify something ( PropertyChanged()) that the value has changed. It would be very hard to do with just the field
The first one is public variable which can be accessed from anywhere.
The second one is public property
Check Properties tutorial for details.
Properties have many uses: they can validate data before allowing a
change; they can transparently expose data on a class where that data
is actually retrieved from some other source, such as a database; they
can take an action when data is changed, such as raising an event, or
changing the value of other fields.

Handling deserialization error

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

How to check if a variable is Array or Object?

For deserialising a json object, I had to define a parent class that would contain an object or an array of objects for the child class. It has to be an object if an object was retrieved, or an array of objects if an array was retrieved from the json.
JSON array object
{"y":{"x":[{"data":28}, {"data":56}, {"data":89}]}}
JSON object
{"y":{"x":{"data":28}}}
y is receiving x at a time, and x[] at another time. There is no such condition to determine whether y would recieve an array or an object.
Hence for determining whether I received an array or not, I am checking the IsArray() condition.
I tried
class Y
{
public X x { get { return System.IsArray() ? new X() : new x[] }; set; }
}
class X
{
public int data { get; set; }
}
It isnt working.
System.IsArray() isn't being recognised??
First off, an array is an object. That's a good thing, since it allows these functions to work (both assume using System;):
bool IsArray(object o) { return o is Array; }
bool IsArray(object o) { return o.GetType().IsArray; }
Second, if you want a property whose type can be either X or X[], the property's type needs to be object:
class Y
{
private object _x;
public object x {
get { return _x; }
set
{
if (value.GetType != typeof(X) && value.GetType != typeof(X[]))
throw new ArgumentException("value");
_x = value;
}
}
}
This somewhat ignores the advantage of static typing, as you're using object and checking types at run time. It would really be much simpler to define the property as an array, even for those cases where there's only one value. In such cases, it would be an array whose length is 1.
I've been using the Json.NET Nuget package, and it's been really easy to work with:
string jsonStr = "{'y':{'x':[{'data':28}, {'data':56}, {'data':89}]}}";
dynamic jobject = JsonConvert.DeserializeObject(jsonStr);
bool isArray = jobject.y.x.Type == JTokenType.Array;
bool isObject = jobject.y.x.Type == JTokenType.Object;
Hope this helps!
the property x of Type X in class Y cannot be an array of X if you explicity state it is of type X. Declaring it as an object would be one way to get round this.
If you want to check it is an array I would use a backing field (say _x) and then where you use the property do a check (typeof(_x) == X[])
That could get messy though, my best advice would be set the type of property x to X[] and in the set determine whether the value was an array (if so just set _x = value) or if not add value to an empty array of X
You can try this...
if (obj.GetType().IsArray)
{
...
}
Another way you can do it is,
if (obj is Array) {
...
}

Categories