Вызов Uber API в формате JSON из Unity

Я использую Uber API внутри Unity, и я могу войти в систему, а затем аутентифицироваться, чтобы получить токен, но я столкнулся с препятствием при вызове фактического API.

Я считаю, что моя проблема в том, что мне нужно делать вызов в формате JSON, но я не знаю, как это сделать. Я новичок в HTTP и API в целом. Вот мой код:

    private IEnumerator TestRequest(){
    Debug.Log(sToken);
    WWWForm form = new WWWForm();
    //WWW www = new WWW();
    form.headers["Content-Type"] = "application.json";
    form.headers["Authorization"] = "Bearer " +sToken;
    form.AddField( "fare_id", "abcd");
    form.AddField("product_id", "a1111c8c-c720-46c3-8534-2fcdd730040d");
    form.AddField("start_latitude", "37.761492");
    form.AddField("start_longitude", "-122.42394");
    form.AddField("end_latitude", "37.775393");
    form.AddField("end_longitude", "-122.417546");

    yield return null;

    using(UnityWebRequest uweb = UnityWebRequest.Post("https://sandbox-
    api.uber.com/v1.2/requests", form)){
        yield return uweb.Send();
        if(uweb.isError) Debug.Log(uweb.error);
        else Debug.Log(uweb.downloadHandler.text);
        //GetVals(uweb.downloadHandler.text);
    }
}

Это работает для меня в других областях, но не в этой, и я думаю, что это как-то связано с типом контента JSON, но я не могу понять, как отправить его в правильном формате. Извините, что я не могу быть более конкретным, я только разбираюсь в этом.

Любая помощь будет принята с благодарностью!


person Nahele Allan-Moon    schedule 05.05.2017    source источник
comment
Интересно, следует ли вам сделать: form.headers["Content-Type"] = "application/json" (обратите внимание на косую черту вместо точки)   -  person Charlyn G    schedule 05.05.2017
comment
также является ли sToken токеном сервера? Если это так, то эта строка должна быть: form.headers["Authorization"] = "Token " +sToken;   -  person Charlyn G    schedule 05.05.2017
comment
Спасибо @Charlyn, но это не решило проблему. Мне нужно было изменить его на application/json, и я также пробовал и Bearer, и Token, но ни один из них не работал. Я также пробовал с токеном доступа, который я могу сгенерировать из панели разработчика, что наводит меня на мысль, что проблема связана с форматом, в котором я передаю информацию. Хотя не уверен.   -  person Nahele Allan-Moon    schedule 06.05.2017
comment
Я думаю о формате JSON из-за этого сообщения SO: android" title="uber недопустимые учетные данные oauth 2 0 предоставили аутентификацию uber в android"> stackoverflow.com/questions/40945491/, но я не могу понять, как использовать функциональность Unity C #, доступную для репликации того же вещь.   -  person Nahele Allan-Moon    schedule 06.05.2017


Ответы (2)


Как уже упоминалось, application.json должно быть application/json.

Это не единственная проблема. Поскольку это json, вам не нужно использовать класс WWWForm. Создайте класс для хранения данных Json, а затем создайте новый его экземпляр. Преобразуйте экземпляр в json и передайте его второму параметру функции UnityWebRequest Post.

UnityWebRequest:

Для UnityWebRequest используйте перегрузку UnityWebRequest Post(string uri, string postData);, которая позволяет передавать URL-адрес и данные json. Затем вы используете SetRequestHeader для установки заголовков.

[Serializable]
public class UberJson
{
    public string fare_id;
    public string product_id;
    public double start_latitude;
    public double start_longitude;
    public double end_latitude;
    public double end_longitude;
}

void Start()
{
    postJson();
}

string createUberJson()
{
    UberJson uberJson = new UberJson();

    uberJson.fare_id = "abcd";
    uberJson.product_id = "a1111c8c-c720-46c3-8534-2fcdd730040d";
    uberJson.start_latitude = 37.761492f;
    uberJson.start_longitude = -122.42394f;
    uberJson.end_latitude = 37.775393f;
    uberJson.end_longitude = -122.417546f;

    //Convert to Json
    return JsonUtility.ToJson(uberJson);
}

void postJson()
{
    string URL = "https://sandbox-api.uber.com/v1.2/requests";

    //string json = "{ \"fare_id\": \"abcd\", \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\", \"start_latitude\": 37.761492, \"start_longitude\": -122.423941, \"end_latitude\": 37.775393, \"end_longitude\": -122.417546 }";

    string json = createUberJson();

    string sToken = "";

    //Set the Headers
    UnityWebRequest uwrq = UnityWebRequest.Post(URL, json);
    uwrq.SetRequestHeader("Content-Type", "application/json");
    uwrq.SetRequestHeader("Authorization", "Bearer " + sToken);

    StartCoroutine(WaitForRequest(uwrq));
}

IEnumerator WaitForRequest(UnityWebRequest uwrq)
{
    //Make the request
    yield return uwrq.Send();
    if (String.IsNullOrEmpty(null))
    {
        Debug.Log(uwrq.downloadHandler.text);
    }
    else
    {
        Debug.Log("Error while rececing: " + uwrq.error);
    }
}

Если UnityWebRequest не сработало, используйте WWW. Были сообщения об ошибках с UnityWebRequest, но я лично не сталкивался с ними.

Интернет:

Для WWW используйте перегрузку конструктора public WWW(string url, byte[] postData, Dictionary<string, string> headers);, которая принимает URL-адрес, данные и заголовки в одном вызове функции.

[Serializable]
public class UberJson
{
    public string fare_id;
    public string product_id;
    public double start_latitude;
    public double start_longitude;
    public double end_latitude;
    public double end_longitude;
}

void Start()
{
    postJson();
}

string createUberJson()
{
    UberJson uberJson = new UberJson();

    uberJson.fare_id = "abcd";
    uberJson.product_id = "a1111c8c-c720-46c3-8534-2fcdd730040d";
    uberJson.start_latitude = 37.761492f;
    uberJson.start_longitude = -122.42394f;
    uberJson.end_latitude = 37.775393f;
    uberJson.end_longitude = -122.417546f;

    //Convert to Json
    return JsonUtility.ToJson(uberJson);
}


void postJson()
{
    string URL = "https://sandbox-api.uber.com/v1.2/requests";

    //string json = "{ \"fare_id\": \"abcd\", \"product_id\": \"a1111c8c-c720-46c3-8534-2fcdd730040d\", \"start_latitude\": 37.761492, \"start_longitude\": -122.423941, \"end_latitude\": 37.775393, \"end_longitude\": -122.417546 }";

    string json = createUberJson();

    string sToken = "";

    //Set the Headers
    Dictionary<string, string> headers = new Dictionary<string, string>();
    headers.Add("Content-Type", "application/json");
    headers.Add("Authorization", "Bearer " + sToken);
    //headers.Add("Content-Length", json.Length.ToString());

    //Encode the JSON string into a bytes
    byte[] postData = System.Text.Encoding.UTF8.GetBytes(json);

    WWW www = new WWW(URL, postData, headers);
    StartCoroutine(WaitForRequest(www));
}

IEnumerator WaitForRequest(WWW www)
{
    yield return www;
    if (String.IsNullOrEmpty(null))
    {
        Debug.Log(www.text);
    }
    else
    {
        Debug.Log("Error while rececing: " + www.error);
    }
}
person Programmer    schedule 06.05.2017
comment
Большое спасибо @Programmer! Использование www действительно работает! Похоже, что есть некоторая проблема с аутентификацией при использовании UnityWebRequest, что немного расстраивает, но, по крайней мере, это работает! Я очень ценю, что вы нашли время, чтобы помочь мне понять это, это последний кусочек головоломки! - person Nahele Allan-Moon; 06.05.2017
comment
Да, это действительно ошибка с UnityWebRequest. Хорошо, что WWW — это вариант и решение. Удачного кодирования! - person Programmer; 06.05.2017

Если вы укажете ContentType как application/json, я полагаю, вы также должны отправить контент в реальном Json. Я записал пример. Это использует Newtonsoft Json, но вы должны быть в порядке с любой реализацией Json. Кроме того, это более или менее псевдокод, возможно, вам придется внести некоторые окончательные корректировки.

using Newtonsoft.Json;

private IEnumerator TestRequest()
{
    var jsonObject = new
    {
        fare_id = "abcd",
        product_id = "a1111c8c-c720-46c3-8534-2fcdd730040d",
        start_latitude = 37.761492f,
        start_longitude = -122.42394f,
        end_latitude = 37.775393f,
        end_longitude = -122.417546f,
    };

    MemoryStream binaryJson = new MemoryStream();
    using (StreamWriter writer = new StreamWriter(binaryJson))
        new JsonSerializer().Serialize(writer, jsonObject);

    using (UnityWebRequest uweb = UnityWebRequest.Post("https://sandbox-api.uber.com/v1.2/requests"))
    {
        uweb.SetRequestHeader("Authorization", "Bearer " + sToken);
        uweb.SetRequestHeader("Content-Type", "application/json");

        UploadHandlerRaw uploadHandler = new UploadHandlerRaw(binaryJson.ToArray());
        uweb.uploadHandler = uploadHandler;

        yield return uweb.Send();

        if(uweb.isError)
            Debug.Log(uweb.error);
        else
            Debug.Log(uweb.downloadHandler.text);
    }
}
person Thomas Hilbert    schedule 06.05.2017
comment
Спасибо, что нашли время, чтобы взглянуть на этого @Thomas Hilbert, я попробовал это и до сих пор не могу заставить его работать. Я использовал структуру вне Coroutine для хранения значений, но когда я вызвал JsonSerializer в BinaryJson MemoryStream, это было 0 байт. Поэтому вместо этого использовалось следующее: string s = JsonUtility.ToJson(j); byte[] byteArray = System.Text.Encoding.UTF8.GetBytes(s); Вы знаете, должно ли это все еще работать? Извините за нубство! - person Nahele Allan-Moon; 06.05.2017
comment
Извините за мой поздний ответ. Исправил пример, теперь binaryJson корректно заполняется данными. JsonUtility тоже будет работать, однако с ним нельзя использовать анонимные типы, поэтому в примере я предпочел Newtonsoft.Json. - person Thomas Hilbert; 08.05.2017