在我的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
修改
使用带有匿名对象的动态列表是否存在副作用或意外问题?
答案 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
并计算客户端的对象数量?
不使用匿名类型。您正在创建一个匿名类型的单个对象,其中包含两个属性:MyWeekdayCar
和MyWeekendCar
,它们是两种不同的匿名类型。
所以你没有拥有一组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类选中。当然,如果您在客户端添加\删除汽车,这种方法需要更加聪明。如果您确实需要这个,请告诉我,我可以进一步建议
希望这有帮助!