我想使用facebook的API,我觉得很难将对象转换为urlEncoded。 所以,现在我有类似的东西:
string postData = JsonConvert.SerializeObject(req);
postData = postData.Replace(@"\", "");
postData = HttpUtility.UrlEncode(postData);
byte[] data = Encoding.UTF8.GetBytes(postData);
string facebookUrl = "https://graph.facebook.com/v2.5/";
问题是facebook不接受jsons但是UrlEncoded数据,如果我错了,就会纠正我。
所以,我非常确定将对象转换为UrlEncoded字符串在.Net 4.5.1中是不可能的,因为我试图使用这些问题的一些答案,这些问题在此之前它们并不适用于我。
例如:
var result = new List<string>();
foreach (var property in TypeDescriptor.GetProperties(req))
{
result.Add(property.Name + "=" + property.GetValue(req));
}
postData = string.Join("&", result);
但根本没有定义.Name
和.GetValue
。
希望得到一些帮助,TIA。
我使用的对象:
internal sealed class FacebookValidationRequest
{
public string access_token;
public fbReq[] batch;
public string method;
public string format;
public int pretty;
public int suppress_http_code;
public string debug;
public FacebookValidationRequest(string appId, string userToken)
{
access_token = userToken;
batch = new[]
{
//test code
new fbReq("GET", "me"),
new fbReq("GET", "me/friends?limit=50") //,
//new fbReq("GET", "app?access_token=" + userToken)
};
method = "post";
format = "json";
pretty = 0;
suppress_http_code = 1;
debug = "all";
}
}
internal sealed class fbReq
{
public string method;
public string relative_url;
public fbReq(string m, string url)
{
method = m;
relative_url = url;
}
}
FacebookValidationRequest req = new FacebookValidationRequest(appToken, userToken);
此外,还获取了facebook debugger site
的令牌facebook在编码后想要反对的样子:
的access_token =即为MyToken&安培;批次=%5B%7B%22method%22%3A%22GET%22%2C%20%22relative_url%22%3A%22me%22%7D%2C%7B%22method%22%3A% 22GET%22%2C%20%22relative_url%22%3A%22me%2Ffriends%3Flimit%3D50%22%7D%5D&安培;调试=所有&安培;字段= ID%2Cname&安培;格式= JSON&安培;方法=交&安培;漂亮= 0&安培; suppress_http_code = 1
答案 0 :(得分:1)
在我看来,最简单的方法是使用Attributes来描述你的属性,就像.Net Json的DataContract
系统一样。基本上,您为要序列化的每个属性分配一个属性,并使该属性包含将其序列化为的名称。我不认为你想要实际编写自己的DataContractSerializer,所以简单地创建你自己的Property类和使用反射的简单序列化器可能更容易。
属性类:
[AttributeUsage(AttributeTargets.Property)]
public sealed class UrlEncodeAttribute : System.Attribute
{
public String Name { get; private set; }
public UrlEncodeAttribute(String name)
{
this.Name = name;
}
}
然后,要应用于您的数据类......将属性放在所有属性上:
internal sealed class FacebookValidationRequest
{
[UrlEncodeAttribute("access_token")]
public String AccessToken { get; set; }
[UrlEncodeAttribute("method")]
public String Method { get; set; }
[UrlEncodeAttribute("format")]
public String Format { get; set; }
[UrlEncodeAttribute("pretty")]
public Int32 Pretty { get; set; }
[UrlEncodeAttribute("suppress_http_code")]
public Int32 SuppressHttpCode { get; set; }
[UrlEncodeAttribute("debug")]
public string Debug { get; set; }
public fbReq[] Batch { get; set; }
[UrlEncodeAttribute("batch")]
public String BatchString
{
get
{
// put your json serialization code here to return
// the contents of Batch as json string.
}
}
}
如您所见,Batch
不拥有UrlEncodeAttribute
,而其字符串代表BatchString
确实。它的get
是序列化程序调用的,因此您可以将转换代码放在那里。
另请注意,由于您在属性中提供的文本名称,您的属性不需要具有您在序列化中实际获得的名称,在我看来,它看起来很多更清洁。 C#自己对xml和json的序列化工作方式相同。
现在,让我们看一下实际的序列化,使用反射来获取这些属性:
public static String Serialize(Object obj, Boolean includeEmpty)
{
// go over the properties, see which ones have a UrlEncodeAttribute, and process them.
StringBuilder sb = new StringBuilder();
PropertyInfo[] properties = obj.GetType().GetProperties();
foreach (PropertyInfo p in properties)
{
object[] attrs = p.GetCustomAttributes(true);
foreach (Object attr in attrs)
{
if (attr is UrlEncodeAttribute)
{
UrlEncodeAttribute fldAttr = ((UrlEncodeAttribute)attr);
String objectName = fldAttr.Name;
Object objectDataObj = p.GetValue(obj, null);
String objectData = objectDataObj == null ? String.Empty : objectDataObj.ToString();
if (!String.IsNullOrEmpty(objectData) || includeEmpty)
{
objectData = HttpUtility.UrlEncode(objectData);
objectName= HttpUtility.UrlEncode(objectName);
if (sb.Length > 0)
sb.Append("&");
sb.Append(objectName).Append("=").Append(objectData);
}
break; // Only handle one UrlEncodeAttribute per property.
}
}
}
return sb.ToString();
}
可以通过在UrlEncodeAttribute类中包含序列化方法属性(可能最好使用枚举)来实现更高级的版本,因此您可以简单地指定使用json动态序列化数组。您显然需要将实际的json转换器放入Serialize函数中。我认为在虚拟属性上使用getter,因为准备方法更简单,这里。
显然,调用它只是这样:(假设此处Serialize()
函数位于名为UrlEncodeSerializer
的类中
FacebookValidationRequest fbreq = new FacebookValidationRequest();
// fill your data into fbreq here
// ...
// includeEmpty is set to true for testing here, but normally in
// UrlEncoded any missing property is just seen as empty anyway, so
// there should be no real difference.
String serialized = UrlEncodeSerializer.Serialize(fbreq, true);