How to parse JSON received in MVC Controller

2019-07-09 02:39发布

问题:

I have a JSON file that is being sent to an MVC controller via a POST request from the client side. Since there isn't a direct way to store JSON in C#, I'm trying to create models to store the data. Here is the structure of the JSON:

{
    "SubscriptionsType1": {
        "Obj1": {
            "Value1": "3454234",
            "Value2": "345643564",
            "Value3": "665445",
            "Value4": "True"
        },
        "Obj2": {
            "Value1": "3454234",
            "Value2": "345643564",
            "Value3": "665445",
            "Value4": "True"
        },
        "Obj3": {
            "Value1": "3454234",
            "Value2": "345643564",
            "Value3": "665445",
            "Value4": "True"
        }
    },
"SubscriptionsType2": {
                "Obj1": {
                    "Value1": "3667635",
                    "Value2": "34563456",
                    "Value3": "234545",
                    "Value4": "False"
                },
                "Obj2": {
                    "Value1": "97865",
                    "Value2": "356356",
                    "Value3": "665757445",
                    "Value4": "True"
                },
                "Obj3": {
                    "Value1": "3454234",
                    "Value2": "345643564",
                    "Value3": "665445",
                    "Value4": "False"
                }
            },
    //etc..

    }

The models are the following:

  public class RootObject {
        public IEnumerable<SubscriptionObj> Subscriptions { get; set; }
}


public class Subscriptions {
    IEnumerable<SubscriptionObj> objs;
}


public class SubscriptionObj
{
    public Int64 Value1 {get;set;}
    public Int64 Value2 {get;set;}
    public Int64 Value3 {get;set;}
    public Boolean Value4 {get;set;}
}

For some reason, if I create the model classes with this structure, the Root Object is still null after the it is passed the JSON object from the controller. However, when I explicitly create attributes to store each value of the JSON object, it works. Since the JSON object doesn't have a fixed number of elements, I need a way to dynamically store each attribute. How can this be done?

回答1:

Because of the varying key in the root object and subscriptions, you should use a dictionary.

public class RootObject : Dictionary<string, Subscriptions> { }

public class Subscriptions : Dictionary<string, SubscriptionObj> { }

public class SubscriptionObj {
    public Int64 Value1 {get;set;}
    public Int64 Value2 {get;set;}
    public Int64 Value3 {get;set;}
    public Boolean Value4 {get;set;}
}

The above would serialize to the JSON in the OP but you loose the strongly typed keys/property names



回答2:

The json corresponding to your c# classes should use arrays, something like

{
    "Subscriptions": [ 
    {  "Obj": [   
        {
            "Value1": "3454234",
            "Value2": "345643564",
            "Value3": "665445",
            "Value4": "True"
        },
        {
            "Value1": "3454234",
            ...
        },
        {
            "Value1": "3454234",
            ...
        } ] 
    },  //end of Subscription 1
    {  "Obj": [   
        {
            "Value1": "3454234",
            ...
        },
        {
            "Value1": "3454234",
            ...
        },
        {
            "Value1": "3454234",
            ...
        } ] 
    }  //end of Subscription 2
    ] 
}

The c# classes corresponding to your json with no arrays will look something like:

public class ObjType
{
    public string Value1 { get; set; }
    public string Value2 { get; set; }
    public string Value3 { get; set; }
    public string Value4 { get; set; }
}

public class SubscriptionsType
{
    public ObjType Obj1 { get; set; }
    public ObjType Obj2 { get; set; }
    public ObjType Obj3 { get; set; }
}

public class RootObject
{
    public SubscriptionsType SubscriptionsType1 { get; set; }
    public SubscriptionsType SubscriptionsType2 { get; set; }
}


回答3:

for that datastructure i would deserialize the object to dynamic. then you can check if there is "SubscriptionsType1" or "SubscriptionsType2", ...

with the dynamic i would create the model classes and fill them in a self brewed deserialization method/class.

the design of the model is not serialization friendly, can you change the json that you will get by changing the contract with the caller?

if so here is my suggestion:

{ "Subscriptions": [
    {
    "Objects": [{
        "Value1": "3454234",
        "Value2": "345643564",
        "Value3": "665445",
        "Value4": "True"
    },
    {
        "Value1": "3454234",
        "Value2": "345643564",
        "Value3": "665445",
        "Value4": "True"
    },
    {
        "Value1": "3454234",
        "Value2": "345643564",
        "Value3": "665445",
        "Value4": "True"
    }
    ]
},
{
            "Objects": [
            {
                "Value1": "3667635",
                "Value2": "34563456",
                "Value3": "234545",
                "Value4": "False"
            },
            {
                "Value1": "97865",
                "Value2": "356356",
                "Value3": "665757445",
                "Value4": "True"
            },
            {
                "Value1": "3454234",
                "Value2": "345643564",
                "Value3": "665445",
                "Value4": "False"
            }]
        },
//etc..
]
}

your model would change to:

public class RootObject {
        public Subscriptions SubscriptionCollection { get; set; }
}


public class Subscriptions {
    IEnumerable<SubscriptionObj> objs;
}

public class SubscriptionObj
{
    public Int64 Value1 {get;set;}
    public Int64 Value2 {get;set;}
    public Int64 Value3 {get;set;}
    public Boolean Value4 {get;set;}
}

is that what you are trying to get?



回答4:

From your JSON file, we can extract the model classes below:

public class RootModel{
    public SubscriptionTypeModel SubscriptionsType1 { get; set; }

    public SubscriptionTypeModel SubscriptionsType2 { get; set; }

    //etc...
}

public class SubscriptionTypeModel {
    public ObjectModel Obj1 { get; set; }
    public ObjectModel Obj2 { get; set; }
    public ObjectModel Obj3 { get; set; }
}

public class ObjectModel {
    public string Value1 { get; set; }
    public string Value2 { get; set; }
    public string Value3 { get; set; }
    public bool Value4 { get; set; }
}

If the list of subscriptions is dynamic, then you should change your JSON file to look like the one below:

[
{"Subscriptions": [
    {
        "Value1": "3454234",
        "Value2": "345643564",
        "Value3": "665445",
        "Value4": "True"
    },
    {
        "Value1": "3454234",
        "Value2": "345643564",
        "Value3": "665445",
        "Value4": "True"
    },
    {
        "Value1": "3454234",
        "Value2": "345643564",
        "Value3": "665445",
        "Value4": "True"
    }
]}, { "Subscriptions":[
            {
                "Value1": "3667635",
                "Value2": "34563456",
                "Value3": "234545",
                "Value4": "False"
            },
            {
                "Value1": "97865",
                "Value2": "356356",
                "Value3": "665757445",
                "Value4": "True"
            },
            {
                "Value1": "3454234",
                "Value2": "345643564",
                "Value3": "665445",
                "Value4": "False"
            }
        ]}
]