0

I am working on .net console application, and i have this class which I will Deserialzie a returned json on it:-

public class UdfFields
{
    public object udf_pick_34206 { get; set; }
    public string udf_pick_34205 { get; set; }
    public object udf_pick_34202 { get; set; }
    public object udf_mline_35402 { get; set; }
    public object udf_pick_34503 { get; set; }
    public object udf_pick_34502 { get; set; }
    public object udf_pick_35103 { get; set; }
    public object udf_pick_35101 { get; set; }
    public object udf_pick_29744 { get; set; }
    public object udf_sline_35701 { get; set; }
    public string udf_pick_35401 { get; set; }
    public object udf_pick_29753 { get; set; }
}

but the issue i am facing is that on some environments I will have different names for the public object udf_pick_29744 { get; set; } property .. for example it can be as follow:-

public object udf_pick_28744 { get; set; }
OR
public object udf_pick_26744 { get; set; }

so to make my code dynamic I define the following inside the appsetting.json file:-

"Field": "udf_pick_28744",

so can i get the value of the Field from my appsettins.json and dynamically name the property inside the class? and if this is not possible then how i can fix this issue?

Thanks

EDIT

I tired to use JsonProperty as follow,

public class UdfFields
    {
        static IConfiguration config = new ConfigurationBuilder()
           .AddJsonFile("appsetting.json", optional: false).Build();

        string name = config.GetSection("ServiceDesk").GetSection("field").Value;
        public object udf_pick_34206 { get; set; }
        public string udf_pick_34205 { get; set; }
        public object udf_pick_34202 { get; set; }
        public object udf_mline_35402 { get; set; }
        public object udf_pick_34503 { get; set; }
        public object udf_pick_34502 { get; set; }
        public object udf_pick_35103 { get; set; }
        public object udf_pick_35101 { get; set; }
        public object udf_pick_29744 { get; set; }
        public object udf_sline_35701 { get; set; }
        public string udf_pick_35401 { get; set; }
        public object udf_pick_29753 { get; set; }
        [JsonProperty(PropertyName = name)]
        public object riskdesc { get; set; }
    }

but i got this error:-

An object reference is required for the non-static field, method, or property 'UdfFields.name'

John John
  • 1
  • 72
  • 238
  • 501
  • 1
    Check out [ExpandoObject](https://learn.microsoft.com/en-us/dotnet/api/system.dynamic.expandoobject?view=net-5.0). – itsme86 Apr 15 '21 at 20:38
  • If you use Json.NET - you can use `DefaultContractResolver` check here https://stackoverflow.com/a/33290710/5446495 – Genusatplay Apr 15 '21 at 20:48
  • @itsme86 can you advice more on this? how i can use it in my case? – John John Apr 15 '21 at 20:56
  • 1
    Why don't you use ```JsonPropertyAttribute``` to assign a custom json name to the property instead of renaming the property itself. The parameter of the attribute can be changed at runtime. – Morse Apr 15 '21 at 20:58
  • 1
    Why aren't you exposing these as interfaces? You can deserialize that same object type and just have it implement different interfaces with the different names. – Rex Henderson Apr 15 '21 at 20:58
  • @RexHenderson can you check my edit please? – John John Apr 15 '21 at 21:12
  • @Morse it did not work for me can you check my edit – John John Apr 15 '21 at 21:12
  • 1
    Does this answer your question? [Newtonsoft JSON dynamic property name](https://stackoverflow.com/questions/37917164/newtonsoft-json-dynamic-property-name) – Andrei Khotko Apr 15 '21 at 21:16
  • @AndreiKhotko thanks but can you help in getting this working for me.. i am not sure how i need to modify the code? – John John Apr 15 '21 at 21:18
  • I said it can be changed in runtime, not that it can be assigned in such a way. There are examples on SO on how to change the parameter of the attribute in runtime. One of the links was already provided by Andrei here. – Morse Apr 15 '21 at 21:24
  • @johnGu pls, see the answer below – Andrei Khotko Apr 15 '21 at 21:47

1 Answers1

0

It's not possible (as I know) to change the name of the property at runtime. However it's possible to change the name of the property used in serialization logic.

One of the solutions is to mark the UdfFields class as abstract, mark the property udf_pick_29744 (let's call it just udf_pick_dynamic) as abstract and define the children classes which implement the property udf_pick_dynamic with different [JsonProperty(PropertyName)] attribute values. It would be something like this:

internal static class Program
{
    private static void Main(string[] args)
    {
        var config = new ConfigurationBuilder().AddJsonFile("appsetting.json", optional: false).Build();
        var dynamicFieldName = config.GetSection("ServiceDesk").GetSection("field").Value;

        // Get json to be deserialized
        var json = GetJson(); 

        var udfFields = DeserializeJsonWithDynamicFieldName(json, dynamicFieldName);

        // Now you can get either 'udf_pick_29744' or 28744 or 26744 by accessing 'udfFields.udf_pick_dynamic' property
    }

    private static string GetJson()
    {
        // Here is your logic how to get json string
    }

    private static UdfFields DeserializeJsonWithDynamicFieldName(string json, string dynamicFieldName)
    {
        return dynamicFieldName switch
        {
            UdfPickDynamicFieldNames.Pick29744 => JsonConvert.DeserializeObject<UdfFields29744>(json),
            UdfPickDynamicFieldNames.Pick28744 => JsonConvert.DeserializeObject<UdfFields28744>(json),
            UdfPickDynamicFieldNames.Pick26744 => JsonConvert.DeserializeObject<UdfFields26744>(json),
            _ => throw new ArgumentException("Unsupported dynamic field name")
        };
    }
}

internal static class UdfPickDynamicFieldNames
{
    internal const string Pick29744 = "udf_pick_29744";
    internal const string Pick28744 = "udf_pick_28744";
    internal const string Pick26744 = "udf_pick_26744";
}

public abstract class UdfFields
{
    public object udf_pick_34206 { get; set; }
    public string udf_pick_34205 { get; set; }
    public object udf_pick_34202 { get; set; }
    public object udf_mline_35402 { get; set; }
    public object udf_pick_34503 { get; set; }
    public object udf_pick_34502 { get; set; }
    public object udf_pick_35103 { get; set; }
    public object udf_pick_35101 { get; set; }
    
    public abstract object udf_pick_dynamic { get; set; }
    public object udf_sline_35701 { get; set; }
    public string udf_pick_35401 { get; set; }
    public object udf_pick_29753 { get; set; }
}

public sealed class UdfFields29744 : UdfFields
{
    [JsonPropertyName(UdfPickDynamicFieldNames.Pick29744)]
    public override object udf_pick_dynamic { get; set; }
}

public sealed class UdfFields28744 : UdfFields
{
    [JsonPropertyName(UdfPickDynamicFieldNames.Pick28744)]
    public override object udf_pick_dynamic { get; set; }
}

public sealed class UdfFields26744 : UdfFields
{
    [JsonPropertyName(UdfPickDynamicFieldNames.Pick26744)]
    public override object udf_pick_dynamic { get; set; }
}
Andrei Khotko
  • 229
  • 2
  • 15