1

I have the following C# class:

public RuleCondition(string field,
                     Operator @operator,
                     RightValueExpression rightValueExpression)
    {
        _operator = @operator;
        _field = field;
        _rightValueExpression = rightValueExpression;
    }
    public RightValueExpression ValueExpression => _rightValueExpression;
    public string Field => _field;
    public Operator Operator => _operator;
}

public sealed class RightValueExpression
{
    private readonly bool _relativeToBaseline;
    private readonly double _value;
    private readonly RightOperator _operator;
    private readonly PercentOrAbsolute _isPercent;
    public RightValueExpression(bool relativeToBaseline,
                                RightOperator @operator,
                                double value,
                                PercentOrAbsolute isPercent)
    {
        _isPercent = isPercent;
        _operator = @operator;
        _value = value;
        _relativeToBaseline = relativeToBaseline;
    }
    public PercentOrAbsolute IsPercent => _isPercent;
    public RightOperator Operator => _operator;
    public double Value => _value;
    public bool RelativeToBaseline => _relativeToBaseline;
}

public enum Operator
{
    GreaterThan,
    EqualTo,
    LessThan,
    GreaterThanEqualTo,
    LessThanEqualTo
}

public enum RightOperator
{
    Plus,
    Minus,
    Times,
    DividedBy
}
public enum PercentOrAbsolute
{
    Percent,
    Absolute
}

When serialized to Json using Json.Net, I get the following:

var ruleCondition = new RuleCondition("Min", Operator.GreaterThan, new RightValueExpression(relativeToBaseline: true, RightOperator.Plus, 50, PercentOrAbsolute.Percent));
var json = JsonConvert.SerializeObject(ruleCondition);

Json:

{
"ValueExpression": {
    "IsPercent": 0,
    "Operator": 0,
    "Value": 50.0,
    "RelativeToBaseline": true
},
"Field": "Min",
"Operator": 0

}

All fine, however deserializing using Json.Net

var des = JsonConvert.DeserializeObject<RuleCondition>(json);

RightValueExpression in RuleCondition is always null.

Do I need a custom deserializer here?

1

2 Answers 2

2

You can implement custom JsonConverter:

class RuleConditionConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(RuleCondition));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject jo = JObject.Load(reader);

        var @operator = (Operator)jo["Operator"].Value<int>();
        var field = jo["Field"].Value<string>();

        var isPercent = (PercentOrAbsolute)jo["ValueExpression"]["IsPercent"].Value<int>();
        var rigthOperator = (RightOperator)jo["ValueExpression"]["Operator"].Value<int>();
        var value = jo["ValueExpression"]["Value"].Value<double>();
        var relativeToBaseline = jo["ValueExpression"]["RelativeToBaseline"].Value<bool>();


        RuleCondition result = new RuleCondition(field, @operator, new RightValueExpression(relativeToBaseline, rigthOperator, value, isPercent));

        return result;
    }

    public override bool CanWrite
    {
        get { return false; }
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

Then you can use it during deserialization:

var des = JsonConvert.DeserializeObject<RuleCondition>(json, new RuleConditionConverter());
Sign up to request clarification or add additional context in comments.

Comments

1

If you can live with a public setter on ValueExpression property, you can avoid the specialized converter:

  public class RuleCondition
  {
    public RuleCondition(string field,
                     Operator @operator,
                     RightValueExpression rightValueExpression)
    {
      ValueExpression = rightValueExpression;
      Field = field;
      Operator = @operator;
    }

    public RightValueExpression ValueExpression { get; set; }
    public string Field { get; }
    public Operator Operator { get; }
  }

Alternatively you can rename the ValueExpression property to RightValueExpression:

  public class RuleCondition
  {
    public RuleCondition(string field,
                     Operator @operator,
                     RightValueExpression rightValueExpression)
    {
      RightValueExpression = rightValueExpression;
      Field = field;
      Operator = @operator;
    }

    public RightValueExpression RightValueExpression { get; }
    public string Field { get; }
    public Operator Operator { get; }
  }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.