ScriptService
的WebMethod
返回的对象都被包装成一个JSON对象,其中数据存储在名为d
的属性中。这是可以接受的。但我不想将额外的__type
属性提供给客户端,因为我使用jQuery进行手动处理。有可能实现吗?
ScriptService
的WebMethod
返回的对象都被包装成一个JSON对象,其中数据存储在名为d
的属性中。这是可以接受的。但我不想将额外的__type
属性提供给客户端,因为我使用jQuery进行手动处理。不要使用[Serializable]属性。
以下代码就可以实现:
JavaScriptSerializer ser = new JavaScriptSerializer(); string json = ser.Serialize(objectClass);
\"
) - 这必须在客户端处理。为了避免这种情况(双重JSON格式化),请参见https://dev59.com/cXA75IYBdhLWcg3w1sz2#3079326。您还必须使用`System.Web.Script.Serialization`命名空间,该命名空间位于`System.Web.Extensions.dll`中。 - Alex P. [WebMethod]
[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)]
public void Status()
{
MyObject myObject = new MyObject(); // Your class here
var json = Newtonsoft.Json.JsonConvert.SerializeObject(myObject);
HttpContext.Current.Response.Write(json);
}
这应该解决它。
在 System.WebExtensions.dll 中 JavaScriptSerializer 的私有 SerializeValue 方法中, 如果可以解析,则将 __type 添加到内部字典中。
来自 Reflector:
private void SerializeValue(object o, StringBuilder sb, int depth, Hashtable objectsInUse)
{
if (++depth > this._recursionLimit)
{
throw new ArgumentException(AtlasWeb.JSON_DepthLimitExceeded);
}
JavaScriptConverter converter = null;
if ((o != null) && this.ConverterExistsForType(o.GetType(), out converter))
{
IDictionary<string, object> dictionary = converter.Serialize(o, this);
if (this.TypeResolver != null)
{
string str = this.TypeResolver.ResolveTypeId(o.GetType());
if (str != null)
{
dictionary["__type"] = str;
}
}
sb.Append(this.Serialize(dictionary));
}
else
{
this.SerializeValueInternal(o, sb, depth, objectsInUse);
}
}
//Given the following class
[XmlType("T")]
public class Foo
{
internal Foo()
{
}
[XmlAttribute("p")]
public uint Bar
{
get;
set;
}
}
[WebService(Namespace = "http://me.com/10/8")]
[System.ComponentModel.ToolboxItem(false)]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
public class MyService : System.Web.Services.WebService
{
//Return Anonymous Type to omit the __type property from JSON serialization
[WebMethod(EnableSession = true)]
[System.Web.Script.Services.ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json, XmlSerializeString = false)]
public object GetFoo(int pageId)
{
//Kludge, returning an anonymois type using link, prevents returning the _type attribute.
List<Foo> foos = new List<Foo>();
rtnFoos.Add( new Foo(){
Bar=99
}};
var rtn = from g in foos.AsEnumerable()
select g;
return rtn;
}
}
注意:我正在使用继承的JSON类型转换器,该转换器从序列化类型中读取XML序列化属性以进一步压缩JSON。感谢CodeJournal。非常好用。
除了 @sean 的回答使用 JavaScriptSerializer
之外。
当使用 JavaScriptSerializer 并标记方法的 ResponseFormat = WebMessageFormat.Json
时,生成的响应会进行两次 JSON 编码,而且如果生成的响应是 string
类型,它将被放置在双引号之间。
为了避免这种情况,可以使用 这个优秀答案 中提供的解决方案来将内容类型定义为 JSON(覆盖)并流式传输 JavaScriptSerializer
的二进制结果。
来自上述答案的代码示例:
public Stream GetCurrentCart()
{
//Code ommited
var j = new { Content = response.Content, Display=response.Display,
SubTotal=response.SubTotal};
var s = new JavaScriptSerializer();
string jsonClient = s.Serialize(j);
WebOperationContext.Current.OutgoingResponse.ContentType =
"application/json; charset=utf-8";
return new MemoryStream(Encoding.UTF8.GetBytes(jsonClient));
}
JavaScriptSerializer
位于System.Web.Script.Serialization
命名空间中,该命名空间在System.Web.Extensions.dll
中找到,但默认情况下未被引用。
您可以创建自己的返回类型来发送响应。同时,在发送响应时,使用对象作为返回类型。因此,_type属性将被忽略。
var settings = new DataContractJsonSerializerSettings();
settings.EmitTypeInformation = EmitTypeInformation.Never;
DataContractJsonSerializer serializerInput = new DataContractJsonSerializer(typeof(Person), settings);
var ms = new MemoryStream();
serializerInput.WriteObject(ms, personObj);
string newRequest = Encoding.UTF8.GetString(ms.ToArray());
这有点取巧,但对我来说有效(使用C#):
s = (JSON string with "__type":"clsname", attributes)
string match = "\"__type\":\"([^\\\"]|\\.)*\",";
RegEx regex = new Regex(match, RegexOptions.Singleline);
string cleaned = regex.Replace(s, "");
适用于[DataContract]
和[DataContract(Namespace="")]
两种方式