Search Unity

Posting json through UnityWebRequest

Discussion in 'Scripting' started by tdog360, Jun 12, 2017.

  1. tdog360

    tdog360

    Joined:
    May 1, 2017
    Posts:
    6
    Hi I am trying to get unity to work with my Node.js server.
    But for some reason the request body returns my json string as

    Code (JavaScript):
    1. { '{"level":1,"timeElapsed":47.5,"playerName":"Dr Charles Francis"}': '' }
    Seems like the whole string is interpreted as the first field of the json string.
    So here i create the object and stringify it:

    Code (CSharp):
    1. MyClass myObject = new MyClass();
    2. myObject.level = 1;
    3. myObject.timeElapsed = 47.5f;
    4. myObject.playerName = "Dr Charles Francis";
    5. string jsonStringTrial = JsonUtility.ToJson(myObject);
    next op i create the UnityWebRequest and post.
    Code (CSharp):
    1. UnityWebRequest www = UnityWebRequest.Post("http://localhost:3000/api/rawCoords", jsonStringTrial);
    2. www.SetRequestHeader("Accept", "application/json");
    3. yield return www.Send();
    Do you guys have a better idead of passing this json string, am I doing something weird or is there a better way to do this?
     
    siddharth3322 likes this.
  2. tonemcbride

    tonemcbride

    Joined:
    Sep 7, 2010
    Posts:
    1,089
    hayabu4i likes this.
  3. Sir-Gatlin

    Sir-Gatlin

    Joined:
    Jan 18, 2013
    Posts:
    28
    try this:
    Code (CSharp):
    1. IEnumerator Post(string url, string bodyJsonString)
    2.     {
    3.         var request = new UnityWebRequest(url, "POST");
    4.         byte[] bodyRaw = Encoding.UTF8.GetBytes(bodyJsonString);
    5.         request.uploadHandler = (UploadHandler) new UploadHandlerRaw(bodyRaw);
    6.         request.downloadHandler = (DownloadHandler) new DownloadHandlerBuffer();
    7.         request.SetRequestHeader("Content-Type", "application/json");
    8.         yield return request.SendWebRequest();
    9.         Debug.Log("Status Code: " + request.responseCode);
    10.     }
    found here:
    https://forum.unity.com/threads/unitywebrequest-post-url-jsondata-sending-broken-json.414708/
     
  4. Nuces

    Nuces

    Joined:
    Mar 24, 2014
    Posts:
    2
    Hello. Thank-you for this. This seems to have solved my problem. But can you please explain on why this works and why the standard POST example code given on Unity docs doesn't work. here: "https://docs.unity3d.com/ScriptRefe...002.912384649.1608363462-815429442.1596618243"
     
  5. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,735
    The POST method with string data assumes it's sending HTML form and applies URL-encoding. If given JSON, URL-encoding may corrupt it.
     
    Bunny83 likes this.
  6. seantibb

    seantibb

    Joined:
    May 24, 2019
    Posts:
    5
    Just an FYI, this solution worked for me on 2021.1.12f1.
     
  7. Kjaka

    Kjaka

    Joined:
    Dec 8, 2015
    Posts:
    18
    Thank you this worked very well for me
     
  8. elguncumayev

    elguncumayev

    Joined:
    Nov 8, 2019
    Posts:
    2
    Thank you a lot, after searching for hours.
     
  9. StarCmd

    StarCmd

    Joined:
    Oct 7, 2010
    Posts:
    10
    Every year, a thanks ;-)
     
  10. mwendaenrique5

    mwendaenrique5

    Joined:
    May 10, 2020
    Posts:
    3

    This works like a Charm. Thanks
     
  11. Eyliess

    Eyliess

    Joined:
    Oct 23, 2016
    Posts:
    1
    Awesome, Thanks!
     
  12. gigazelle

    gigazelle

    Joined:
    May 6, 2017
    Posts:
    13
    Important! Don't forget to dispose the UnityWebRequest after sending the data. Just add
    request.Dispose();
    after
    Debug.Log();
    .

    If you don't, you'll get a memory leak error saying that a native collection has not been disposed. Otherwise, this code works great!
     
    Juiceman876 and o2dp like this.
  13. Aurimas-Cernius

    Aurimas-Cernius

    Unity Technologies

    Joined:
    Jul 31, 2013
    Posts:
    3,735
    That's not exactly the case. Garbage collection will release the memory eventually. But without dispose you do keep it for much longer than necessary.
    Instead of calling Dispose() explicitly, I recommend to use using construct.
     
    Bunny83 likes this.
  14. nickhudson2244

    nickhudson2244

    Joined:
    Mar 18, 2019
    Posts:
    15
    For anyone wondering, the correct way would be


    Code (CSharp):
    1.  
    2. using (UnityWebRequest www = UnityWebRequest.Post(uri, payload))
    3.             {
    4.                 //Your code here
    5.             }
     
    o2dp and Bunny83 like this.
  15. FlawedFacts

    FlawedFacts

    Joined:
    Mar 31, 2020
    Posts:
    1
    Thank you so much! I've spent hours trying to fix this.
     
  16. siddharth3322

    siddharth3322

    Joined:
    Nov 29, 2013
    Posts:
    1,049
    One thing, I can't able to understand.
    Why we enclose UnityWebRequest within Using construct?
    Just for garbage collection purpose.
    Already we are adding the code within IEnumerator.
     
  17. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,736
    Because it implements the
    IDisposable
    interface.
     
    Bunny83 and siddharth3322 like this.
  18. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,000
    Right. The exact reason why a class may implement the IDisposable interface can vary. Though in most cases its because the class uses some native resources that should be released as soon as possible. This is usually the case for things like file handles, or network sockets. As it was mentioned above, most managed .NET classes which wrap native resources would usually clean up the native resource when the object is garbage collected. However it's not guaranteed when (or if at all) the GC will run. So it's possible that file handles or sockets get blocked for a long period of time or even pile up when you do several requests in succession. The explicit "Dispose" call will resolve this issue.

    Of course you could call Dispose manually at the end, however the using statement ensures that Dispose is called, even when an exception happens inside the using block. Whenever the using block is exited, it will make sure Dispose is called.

    So code like

    Code (CSharp):
    1. using (var www = UnityWebRequest.Post(uri, payload))
    2. {
    3.     // your code
    4. }
    would translate to something like
    Code (CSharp):
    1.  
    2. {
    3.     UnityWebRequest www;
    4.     try
    5.     {
    6.         www = UnityWebRequest.Post(uri, payload))
    7.         // your code
    8.     }
    9.     finally
    10.     {
    11.         www.Dispose();
    12.     }
    13. }
    So no matter what happens, it would make sure Dispose is called at the end.
     
    siddharth3322 likes this.
  19. siddharth3322

    siddharth3322

    Joined:
    Nov 29, 2013
    Posts:
    1,049
    @Bunny83 Thank you sir for making this concept clear :)
     
  20. michaelday008

    michaelday008

    Joined:
    Mar 29, 2019
    Posts:
    135
    That's odd. I tried the using statement here, and I'm still getting "A Native Collection has not been disposed, resulting in a memory leak."

    I even tried taking it out of the using block, and manually calling Dispose() and it's still happening

    Unity 2021.3.28f1

    Edit: The solution was in this thread. The problem was I was sending json data, and needed to use new UnityWebRequest() instead of UnityWebRequest.Post

    https://forum.unity.com/threads/unity-2021-unitywebrequest-native-collection-memory-leak.1175612/
     
    Last edited: Aug 19, 2023
  21. nickhudson2244

    nickhudson2244

    Joined:
    Mar 18, 2019
    Posts:
    15
    I know this is old but it still appears a lot of people are struggling with it. For me simply disposing of the WebRequest did not work. What did work for me was disposing of each module of the WebRequest. Which looks like this:


    Code (CSharp):
    1. var webRequest = UnityWebRequest.Post(url, UnityWebRequest.kHttpVerbPOST);
    2.  
    3. webRequest.uploadHandler.Dispose();
    4. webRequest.downloadHandler.Dispose();            
    5. webRequest.Dispose();
    6.  
     
  22. Bunny83

    Bunny83

    Joined:
    Oct 18, 2010
    Posts:
    4,000
    This makes no sense as the Dispose method of the UnityWebRequest does dispose the up / download handlers if they exists. Have a look.

    The auto-disposal of the handler could be disabled, however by default they would be disposed with the webrequest.
     
    siddharth3322 likes this.
  23. nickhudson2244

    nickhudson2244

    Joined:
    Mar 18, 2019
    Posts:
    15
    Oh okay I was not aware. Not sure why that change fixed it for me.

    Do you have another fix? If I create a webrequest and then dispose of the object, it will still throw the error. Is it a unity bug?