Search code examples
c#jsonjson.net

c#: deserializing a JSON containing a local property


I deserialize a JSON which looks like this:

{
    "id": "FF478946-8536-4295-AC58-F6C3D2B4E5CC",
    "title": "This is a Title with an escaped variable: {VariableName}",
    "weight": 50
}

To a corresponding object using Newtonsoft:

public class Event
{
    public string Id { get; set; }
    public string Title { get; set; }
    public int Weight { get; set; }
}

And then I want to print the string Title which refers to a local string property in code. VariableName

private string VariableName { get; set; }
private Event CurrentEvent { get; set; }

public void OnNextEventClicked()
{
   Log(CurrentEvent.Title);
}

I tried to somehow escape the variable with different approaches like backslash ("title": "This is a Title with an escaped variable: \"VariableName\"") or curly brackets like in the code above but i failed... C# always treats the escaped variable as a normal part of the Title string.

What's the best way to do this? Thanks!


Solution

  • Like @Roman Ryzhiy pointed out in the comments, there is already a good threat about dynamic string interpolation.

    The perfect solution for me was the following based on this answer.

    A helper method using System.Linq.Dynamic:

    public string ReplaceMacro(string value, object @object)
    {
        return Regex.Replace(value, @"{(.+?)}", 
        match => {
            var p = Expression.Parameter(@object.GetType(), @object.GetType().Name);                
            var e = System.Linq.Dynamic.DynamicExpression.ParseLambda(new[] { p }, null, match.Groups[1].Value);
            return (e.Compile().DynamicInvoke(@object) ?? "").ToString();
        });
    }
    

    My full solution:

    JSON:

    {
    "id": "FF478946-8536-4295-AC58-F6C3D2B4E5CC",
    "title": "This is a Title with an escaped variable: {TitleReplacement.VariableName}",
    "weight": 50
    }
    

    C#:

    Data Class:

    public class Event
    {
        public string Id { get; set; }
        public string Title { get; set; }
        public int Weight { get; set; }
    }
    

    Class with replacement string:

    public class TitleReplacement
    {
        public string VariableName { get; set; }
    }
    

    Call it like:

    private Event CurrentEvent { get; set; }
    private TitleReplacement Replacement { get; set; }
    
    public void OnNextEventClicked()
    {
        Log(ReplaceMacro(CurrentEvent.Title, Replacement);
    }