以json方式请求服务器
思路
使用www或者UnityWebRequest的方法
详细的可以直接看这个文档的内容,里面写的十分清楚
代码
https://blog.csdn.net/qq_34818497/article/details/106160110
注意事项:
如果你的请求格式比较复杂(如需要用到list等数据类型的话)
这里根据以往java代码的经验,是需要创建请求内容的实体类,进行数据的封装,然后序列化变成json格式的字符串再进行请求的
这里我是在需要调用的官网上看他们需要的json内容,然后把他们的案例复制粘贴到在线json格式转c#实体类网站进行实体类的获取,然后直接复制到代码中的;然后再把需要的数据封装进实体类即可
注意,java和c#不同,java能在获得实体后进行set,get的操作,c#不同,是直接类.数据的命名就可以赋值和取值了,相对好像比较方便,但我感觉没差(写代码的时候方便,但是看的时候好像没有java更一目了然)扯远了
//将数据封装到对象中,然后序列化变成json格式的字符串
Root requestData = new Root();
List<ContentItem> datas = new List<ContentItem>();
ContentItem dat = new ContentItem();
dat.data = "请求的内容";
datas.Add(dat);
UserInfo info = new UserInfo();
info.uniqueId = "数据";
Data data = new Data();
data.content = datas;
data.userInfo = info;
requestData.data = data;
requestData.key = "数据";
requestData.timestamp = "时间戳";
string jsonData = JsonMapper.ToJson(requestData);
using (UnityWebRequest request = new UnityWebRequest(url, UnityWebRequest.kHttpVerbPOST))
{
request.url = url;
UploadHandler uploader = new UploadHandlerRaw(System.Text.Encoding.UTF8.GetBytes(jsonData));
request.uploadHandler = uploader;
request.uploadHandler.contentType = "application/json";//这一步比较关键,因为默认的请求并不是json格式的
DownloadHandler downloadHandler = new DownloadHandlerBuffer();
//这一步要注意,没有创建的话后面获取数据的时候会报空对象的异常,前面的uploader其实也是,这里就不多次提醒了,实际写的时候你就知道了
request.downloadHandler = downloadHandler;
yield return request.SendWebRequest();
if (request.isHttpError || request.isNetworkError)
{
Debug.Log(request.error);
}
else
{
Debug.Log(request.downloadHandler.text);
}
}
大致就是这个
响应的话看今天能不能完成,可以的话就一起写上来吧~
获得响应体中多重嵌套的数据
思路
和请求的过程有点反方向的感觉
一开始先在官方的案例中获得响应体的json数据,用前面用到的json转实体类将响应体的实体类生成出来,然后在脚本中创建该类
接着把请求回来的json数据用litjson里的jsonmapper类里的toobject方法将json转成实体类的格式
然后根据你的需要获得其中的数据即可
代码
生成的实体类
public class Parameters
{
public string currentTime { get; set; }
public string dateType { get; set; }
}
public class Intent
{
public string code { get; set; }
public string intentName { get; set; }
public string operateState { get; set; }
public Parameters parameters { get; set; }
}
public class Values
{
public string text { get; set; }
}
public class Results
{
public string groupType { get; set; }
public string resultType { get; set; }
public Values values { get; set; }
}
public class RootObject
{
public string globalId { get; set; }
public Intent intent { get; set; }
public List<Results> results { get; set; }
}
RootObject result = JsonMapper.ToObject<RootObject>(request.downloadHandler.text);
这两步看起来很简单,里面有几个问题需要注意
首先
用litjson这个dll的时候,可能会出现各种类型转换的异常导致反序列化失败
简单的说来原因就是因为litjson这个dll没有很好的处理各类型之间的判定
如果你出现了类型转换的异常,请在反序列化之间,给litjson添加类型转换的代码
JsonMapper.RegisterImporter<Int64, String>((Int64 value) =>
{
return (String)(value+"");
});
JsonMapper.RegisterImporter<Int32, String>((Int32 value) =>
{
return (String)(value+"");
});
方法直接复制就好,然后看你的异常里报的错误是哪个类型转哪个类型的时候发生的异常,把这两个类型更新在上面这个方法的参数里即可
如图,前面的是异常中报的第一个类型,后者第二个类型,添加后就相当于给litjson手动加入了这两个类型的转换的方法,在反序列化的时候就不会有类型转换的异常了
接着
如果你的数据是多重嵌套的,你会发现反序列化成功,但不知道怎么拿到那个数据
你可能会一直拿到的是jsondata这个类,又或者是拿到null
其实只要没有报错,反序列化应该就代表着成功了,只是你拿数据的方式不对而已
比如我要拿到
text里数据
首先是要拿到results这个类,然后注意json里,text是放在【】里的,也即是list集合里,你要用results【0】来获得这一整个内容,然后results[0].text才能最终获得你需要的text数据
这对数据类型的识别需要一点要求,我是后面才发现这个问题的,说到底还是自己半路出家才会遇到这个问题
到这里,恭喜你,已经能够成功获得你要的具体数据了,而不用再用string.sprite和其他的来强制读取需要的数据了,这样太精污了
总结:问题都是看起来很难,但你解决了之后会发现好像就那样~加油
2021.4.6更新
以formdata表单方式请求服务器流程
思路
使用www或httpclient里的MultipartFormDataContent类设置表单内容
代码
www版
首先是将服务器开发文档里需要的参数设置好
然后就是使用wwwform这个类里的addfield方法,将参数传入即可
注意,这里不用对www修改什么参数,因为使用了wwwform这个类,好像就默认请求的是表单的方式(这里没有仔细研究)
这个可能相对比较方便,但可能不好看(因为没有明显的设置请求方式为表单的代码)
注意,最好最好就是先在postman里进行模拟,这样才知道用什么形式的数据才能正确访问
题外话,本人就是一直下不到postman的pc版,一直用的网上的在线模拟请求,导致疯狂失败也不知道什么原因
WWWForm form = new WWWForm();
form.AddField("parameters", parameters);
WWW www1 = new WWW(url, form);
yield return www1;
httpclient版:
string str = "";
try
{
HttpClient client = new HttpClient();
var postContent = new MultipartFormDataContent();
Dictionary<string, string> keyValues = new Dictionary<string, string>();
keyValues.Add("parameters", parameters);
//string boundary = string.Format("--{0}", DateTime.Now.Ticks.ToString("x"));
//postContent.Headers.Add("ContentType", $"multipart/form-data, boundary={boundary}");
//postContent.Add(new ByteArrayContent(System.Text.Encoding.UTF8.GetBytes(parameters)));
foreach (var key in keyValues.Keys)
{
postContent.Add(new StringContent(keyValues[key].ToString()), key);
}
HttpResponseMessage response = client.PostAsync(url, postContent).Result;
str = response.Content.ReadAsStringAsync().Result;
Debug.Log(str);
}
catch (Exception ex)
{
Debug.LogError("PostJsonData:" + ex.ToString());
}
只要理清了思路,这里的代码也不难,关键就是使用MultipartFormDataContent这个类,让请求知道你现在需要的是表单方式的请求,然后只要将需要的参数添加到这个类里可以了
这里的parameters参数用的是上面www里的,直接看上面的就可以了
下一步是研究怎么按照在表单里面添加音频数据
加油