这是否正确使用dynamic关键字来返回JSON数据

时间:2012-12-05 20:47:34

标签: c# asp.net asp.net-mvc json

在我的Controller中,我有一个返回JSON数据的动作:

[HttpGet]
public ActionResult AjaxJson(){
    var ret = new List<dynamic>();

    ret.Add(new{
        Make = "Honda",
        Year = 2011,
    });

    ret.Add(new{
        Make = "BMW",
        Fun = true
    });    

    return Json(new { json = ret }, JsonRequestBehavior.AllowGet);
}

我对使用dynamic关键字有点担心,因为列表中的项目实际上是匿名类型。但是现在可以创建一个匿名类型列表。

我的第二个问题(并不重要)是我将JSON数据作为数组返回。在客户端上,要访问Honda,我必须以这种方式引用它:data.json[0].Make

但我希望能够这样做:data.json.MyWeekdayCar.Make

我知道如果我将JSON数据作为对象返回(稍后列出的控制器操作),我可以使用Honda引用data.json.MyWeekdayCar.Make,但我将失去使用{{1}获取其长度的能力}}。有没有办法让两全其美 - 能够使用data.json.length并计算客户端的对象数量?

Controller将JSON数据作为对象返回:

data.json.MyWeekdayCar.Make

修改

使用带有匿名对象的动态列表是否存在副作用或意外问题?

3 个答案:

答案 0 :(得分:0)

如果您想要两全其美,并且您的json格式不会定期更新,请查看JSON C#类生成器:http://jsonclassgenerator.codeplex.com/

每次更新json格式时,都可以重新生成要使用的前端开发人员的类。

在前端,他们可以使用json.net库将json反序列化为生成的类,如下所示:

Car a = JsonConvert.DeserializeObject<Car> (json);

如果这不符合您的要求,我知道的下一个最佳解决方案是按照您的建议使用动态对象。

答案 1 :(得分:0)

  

有没有办法让两全其美 - 能够使用data.json.MyWeekdayCar.Make并计算客户端的对象数量?

不使用匿名类型。您正在创建一个匿名类型的单个对象,其中包含两个属性:MyWeekdayCarMyWeekendCar,它们是两种不同的匿名类型。

所以你没有拥有一组ojects,你有一个对象具有两个属性,所有这些属性都是不同的类型。在创建对象时,您必须添加length属性。

可以尝试的是创建Dictionary而不是普通数组:

var ret = new Dictionary<string,dynamic>();

ret.Add("MyWekedayCar",new{
    Make = "Honda",
    Year = 2011,
});

ret.Add("MyWeekendCar",new{
    Make = "BMW",
    Fun = true
});  

然后我你可以访问它:

data.json.["MyWeekdayCar"].Make
data.json.length

虽然说实话,我对JSON / JavaScript和字典知之甚少,不知道这是否有效。如果不是,我会将其从我的答案中删除。

答案 2 :(得分:0)

所以回答第一个问题,以你的方式使用动态并没有什么特别的错误。

如果不跳过一些篮球,你将无法达到你想要的效果,但有几种选择:

选项1:您可以编写类似这样的服务器端代码:

var honda = new { Make = "Honda", Year = "2011" };
var bmw = new { Make = "Bmw", Fun = true };
var array = new dynamic[] { honda, bmw };

var ret = new
{
    Cars = array,
    Length = array.Length,
    MyWeekDayCar = honda, 
    MyWeekendCar = bmw
};

然后你可以在你的javascript中使用如下(不是你想要的但是关闭):

data.json.MyWeekendCar.Make, 
data.json.Cars.Length
data.json.Cars[0].Make

这种方法的缺点是你必须在服务器端非常具体,所以它可能有点不灵活。但它确实涉及最少的工作。

选项2:保留服务器端代码,但没有长度属性:

var ret = new {
    MyWeekdayCar = new{
        Make = "Honda",
        Year = 2011
    },
    MyWeekendCar = new{
        Make = "BMW",
        Fun = true
    }
};

然后在javascript中创建类作为数据的包装器,允许您以您希望的方式使用它,例如:

CarsClass.prototype = Array.prototype;   // Inherit from array type for length and other functions
function CarsClass(json) {   
    var that = this;   // very important... but you'll need to research this yourself ;)

    for (var key in json)   // loop around all the properties in the object
    {
        if (json.hasOwnProperty(key))
        {
            that[key] = json[key];   // copy each property to our new object
            that.push(json[key]);    // add each property to our internal array
        }
    }    
}

var cars = new CarsClass(  // This is just dummy data, you would use your json
{ 
    MyWeekdayCar : { Make: 'Honda', Year: '2011' },
    MyWeekendCar : { Make: 'BMW', Fun: true },
    AnotherCar: { Make: 'Skoda', FuelEfficient: true} // flexible!
});

alert(cars.MyWeekendCar.Make); // 'BMW'
alert(cars.length); // 3
alert(cars[0].Make); // 'Honda'
alert(cars[2].FuelEfficient); // True

你可以在这个jsfiddle中看到这个:http://jsfiddle.net/m49h5/

正如您在此方法中所看到的,您可以在服务器端添加更多汽车,并且它们将被javascript类选中。当然,如果您在客户端添加\删除汽车,这种方法需要更加聪明。如果您确实需要这个,请告诉我,我可以进一步建议

希望这有帮助!