我正在使用JSON,ASP.NET,typescript / javascript和AngularJS进行网络应用程序设计。
简而言之:
我需要一种最佳实践,通过JSON从服务器向客户端发送数据,使用客户端的JSON字符串创建对象。
我有一个WebServerAPI项目(ASP.NET),其结构如下:
模型类:
public class A {
public property int Id {get; set;}
public property string Name {get; set;}
public property Type Type {get; set;}
}
public class Type {
public property int Id {get; set;}
public property string Name {get; set;}
}
每个模型类的id属于数据库表(主键)中的id。
DataController结构:
public class DataController : ApiController {
// ...
// GET api/a
public IEnumerable<A> Get()
{
// fetches all As from the database
// the facade creates instances of A and Type as required
// (if A has a 'Type' the Type will also fetched an set)
return facade.GetAll<A>();
}
// ...
}
DataController的Get()方法返回JSON结果。
JSON结果如下所示:
[
{"Id":1,
"Type": {"Id":1, "Name":"name1"}
},
{"Id":2,
"Type": {"Id":2, "Name":"name2"}
},
{"Id":3,
"Type": {"Id":1, "Name":"name1"}
}
{"Id":4,
"Type": {"Id":2, "Name":"name2"}
},
{"Id":5,
"Type": {"Id":2, "Name":"name2"}
},
]
正如您在JSON数据中看到的,一些As共享相同的类型。虽然这是有效的JSON,但我想知道这是否是发送数据的最佳做法。
发送这样的内容会不会更好:
[
{"Id":1,
"TypeId": {"Id":1}
},
{"Id":2,
"TypeId": {"Id":2}
},
{"Id":3,
"TypeId": {"Id":1}
}
{"Id":4,
"TypeId": {"Id":2}
},
{"Id":5,
"TypeId": {"Id":2}
},
]
所以我们只得到类型的Id。但是我们必须要求所有可用的类型来识别必须在相应的As中设置哪个类型。哪个可能不好?我认为这可能很慢,因为我必须发送两个查询。
第三个选项可能是在相同的JSON结果中发送所有可用类型和As。
[
{"Types":
[
{"Id":1, "Name":"name1"},
{"Id":2, "Name":"name2"},
]
},
{"As":
[
{"Id":1,
"TypeId": {"Id":1}
},
{"Id":2,
"TypeId": {"Id":2}
},
{"Id":3,
"TypeId": {"Id":1}
}
{"Id":4,
"TypeId": {"Id":2}
},
{"Id":5,
"TypeId": {"Id":2}
}
]
}
]
所以我想知道是否有最好的做法。作为A中的嵌套对象一遍又一遍地发送相同的对象(Type)似乎非常“愚蠢”。
特别是如果我将JSON字符串转换为Typescript对象。
没有任何“存储/缓存”逻辑,我一遍又一遍地创建“相同”对象:
export class A {
public Id: number;
public Name: string;
public Type: Type;
public static fromData(data: any): A {
var a = new A();
a.Id = data.Id;
a.Name = data.Name;
a.Type = Type.fromData(data.Type);
return a;
}
}
export class Type {
public Id: number;
public Name: string;
public static fromData(data: any) : Type {
var type = new Type();
type.Id = data.Id;
type.Name = data.Name;
return type;
}
}
// AngularJS controller
export class AListCtrl {
static $inject = ['$scope', '$http'];
public As: A[] = [];
constructor(private $scope, private $http) {
$scope.AListCtrl = this;
$http.get('http://localhost/api/a').success((data) => {
var as: A[] = [];
for (var i = 0; i < data.length; i++) {
var aData = data[i];
var a = A.fromData(aData);
as.push(a);
}
this.As = as;
});
}
}
创建代表相同类型的不同对象似乎是错误的。因为我在其他语言(C#,Java,C ++)中使用引用很多。使用这种反序列化数据和创建对象的方式根本不允许使用引用(可能这在Web应用程序中是错误的)。我还认为,生成大量无用的对象而不是每种类型的对象是浪费内存和CPU时间。
相当长的帖子,但我希望它能很好地解释我的问题。
总结一下: 我需要一种最佳实践,通过JSON从服务器向客户端发送数据,使用客户端的JSON字符串创建对象。
答案 0 :(得分:3)
我认为您需要定义对您的客户端应用程序最有意义的JSON表示,然后确保以该格式发送数据。我会创建一个自定义序列化程序,使用内置的JavaScriptConverter或可能使用Json.Net提供的序列化程序。仅仅使用内置的串行器似乎没有给出理想的结果。
答案 1 :(得分:2)
API设计中的一个好的经验法则是制作您的json响应以满足您的客户端需求。我确信一些REST纯粹主义者会不同意,但在现实世界中,减少XHR请求和客户端处理的应用程序比遵循教条式的资源建模方法更可取。
让您的数据库/服务器端对象模型抽象泄漏到您的客户端将最终耗费您的时间和精力。如果您序列化数据以满足客户需求,那么即使您的后端实施发生变化,您也可以保留该界面。
答案 2 :(得分:2)
这是一个有趣的问题,我认为没有一个适合所有可能情况的正确答案。
一般来说,第三个选项是我首先选择的选项。它是正确的,因为允许您不复制相同的数据(类型),并且它是有效的,因为所有数据都可用于一个请求,这有助于减少XHR请求到服务器的开销。
现在,其他两个选项对于各种场景都有一些优点。例如,如果数据集很小,您可能不关心复制类型数据。
有人认为我要记住的是选择适合您前端代码的最佳表示。除非这是您想要与其他客户共享的通用API,否则我建议让后端和前端协同工作以获得最佳速度,同时在客户端保持代码更简单。
希望有所帮助
答案 3 :(得分:1)
我个人认为发送的JSON是数据驱动的。从这个意义上讲,它应该独立于客户端或您正在使用的数据库结构。
例如,如果您检索一些Foo
,则JSON应包含客户端might want to use
的所有相关信息,否则您将最终重写为每个潜在客户提供API的数据。我倾向于尝试从第三方的角度来看待它;
总结一下:
[
{"Id":1,
"Type": {"Id":1, "Name":"name1"}
},
{"Id":2,
"Type": {"Id":2, "Name":"name2"}
},
{"Id":3,
"Type": {"Id":1, "Name":"name1"}
}
{"Id":4,
"Type": {"Id":2, "Name":"name2"}
},
{"Id":5,
"Type": {"Id":2, "Name":"name2"}
},
]
在您的情况下似乎有效。