0

I've been writing a few customconverters, extending Newtonsofts JsonConverter and stumbled on a little problem. Say I have two properties on a class, but they cannot be the same value. Is it possible to find the value of another property in a converter... for example, say I have a model like so.

I'd want to be able to check the value of Surname in CustomCompareConverter to ensure its not the same value as Firstname

public class Person
{
    [JsonConverter(typeof(CustomCompareConverter), "Surname")]
    public string Firstname { get; set; }

    public string Surname { get; set; }
}
```
user2883072
  • 217
  • 3
  • 12
  • You can't access the parent's properties inside a `ReadJson()` method for a child, perhaps because a JSON object is an *unordered set of name/value pairs* so the parent properties might not have been read in and deserialized. See e.g.[How to conditionally deserialize JSON object based on another JSON property?](https://stackoverflow.com/q/38357864/3744182). Consider doing your validations in an [`[OnDeserialized]`](https://www.newtonsoft.com/json/help/html/SerializationCallbacks.htm) event instead. Does this answer your question? – dbc Jan 05 '20 at 18:59

1 Answers1

1

You are trying to do multiple things with the json deserialization process that really should be separated

  1. converting some external json into your domain object

  2. validating the domain object.

The fact that the Surname cannot match the FirstName property is a business rule of your domain. So keep that within your domain. You can:

  1. write a separate validator class that will check the state of your person object and return a list of validation failures
  2. implement IValidatableObject on your Person class and implement the interface
  3. write a custom validator like in this SO question

Use the JSON deserialization process as an anti-corruption layer to keep the details of external systems out of your your domain structure. Once you've take the extenal object and converted it to your domain object then use conventional means to validate that your domain object.

Fran
  • 6,440
  • 1
  • 23
  • 35
  • Which generally I agree with but... The fact that you've already serialized to an object means you've lost the context of where that validation occurs. Take an example where I have a list of customers. Validation of the object itself does not give you any context on which customer the validation has occured has failed. Is it customer 1 or 1000? That is the big problem with the whole validation piece (unless someone tells me otherwise). – user2883072 Jan 08 '20 at 14:16
  • You would be calling Validate on each item in the list. How would you NOT know which one failed? – Fran Jan 08 '20 at 14:31
  • Let me rephrase sorry. Of course I'd know which person object had failed validation. I cannot tell the consumer it was Customer[12].Firstname that was the problem (unless I'm doing something wrong). All I can say is that the customer being validated is wrong.So if I have 3 customers in a list of 100 that have failed all I can do is output 3 error messages. – user2883072 Jan 08 '20 at 14:43
  • If you use IValidatableObject you get an IEnumerable so you know the object that failed and the failures. what else do you need? – Fran Jan 08 '20 at 14:49
  • it doesn't tell me 1) the exact item in the collection that has failed 2) the line in the request that's failed 3) the position in the file. It also means you get two sets of errors. The first is json validation and the second is object validation. It's not a great user experience is it. They potentially have to submit the request twice to get a working rest service call. – user2883072 Jan 08 '20 at 15:09