-1
\$\begingroup\$

I have been trying to work out a subscription form for my game and thanks to you guys here, I came to a solution which works but still needs some changes.

The idea is to have an input field in the scene that takes the users email and convert it into JSON (to do a POST request). I have made the post request and everything works fine but I have to manually type the email in the inspector. What I would want is to get that value from the input field!

    public class testing : MonoBehaviour
    {
        public TMP_InputField myField;
        //public InputField field;
        [SerializeField]
        private Email _email = new Email();
        private string URL = "";

        public void SaveData()
        {
            string data = JsonUtility.ToJson(_email); // this part here needs to be like _email.text
            System.IO.File.WriteAllText(Application.persistentDataPath + "Data.json", data);
            StartCoroutine(SaveIntoJson(URL , data));
        }
        IEnumerator SaveIntoJson(string url, string data)
        {
            var request = new UnityWebRequest(url, UnityWebRequest.kHttpVerbPOST);
            request.SetRequestHeader("Content-Type", "application/json");
            var jsonBytes = Encoding.UTF8.GetBytes(data);
            request.uploadHandler = new UploadHandlerRaw(jsonBytes);
            request.downloadHandler = new DownloadHandlerBuffer();
    
            yield return request.SendWebRequest();
            if (request.isNetworkError || request.isHttpError)
            {
                Debug.Log(request.error);
                Debug.Log(request.downloadHandler.text);
            }
            else
            {
                Debug.Log("Form upload complete!");
            }
            Debug.Log(data);
        }
    }
    [System.Serializable]
    public class Email
    {
        public List<Profiles> profiles = new List<Profiles>();
    }
    [System.Serializable]
    public class Profiles
    {
        [SerializeField]
        public string email; // this part here works but i need to type the email in the inspector
    }

also the requirements for the json are like this

 {"profiles":[{"email":"testing@tes.com"}]}
\$\endgroup\$
6
  • 1
    \$\begingroup\$ and what is preventing you from adding an input field to the scene and read the value from there? \$\endgroup\$ – Zibelas Mar 8 at 12:16
  • \$\begingroup\$ json wont accept anything other than objects and currently im formating it before sending it. i did try the obvious route but it didnt save the string in the format i need it to and it reads null, the obvious solution being : string data = JsonUtility.ToJson(myField.text); \$\endgroup\$ – stratos la Mar 8 at 12:19
  • \$\begingroup\$ Because it does not know it is from type Profiles. Something like Profiles profil = new Profiles() and profil.email = myField.text and afterwards JsonUtility.ToJson(profil). You could add as well a custom constructor to the Profiles to save one line. \$\endgroup\$ – Zibelas Mar 8 at 12:21
  • \$\begingroup\$ i do try it like this but it doesnt get the profiles part public void SaveData() { Profiles profile = new Profiles(); profile.email = field.text; string data = JsonUtility.ToJson(profile); System.IO.File.WriteAllText(Application.persistentDataPath + "Data.json", data); StartCoroutine(SaveIntoJson(URL , data)); } \$\endgroup\$ – stratos la Mar 8 at 12:36
  • \$\begingroup\$ You mean your Email that contains a list? Did you create it and added your Profiles to it? Without posting how your json looks like, the comment was more like how it should be used. See Philips answer for more details \$\endgroup\$ – Zibelas Mar 8 at 12:39
1
\$\begingroup\$

JsonUtility.ToJson only works with objects of a class which inherits from MonoBehaviour or ScriptableObject or which has the [Serializable] attribute. So when you want to use it to create a Json message for some external API, then you should build classes with the [Serializable] attribute which mimic the JSON objects that API expects.

When that API exects a format like this:

 {"profiles": [
     {"email":"email1@example.com"}, 
     {"email":"email2@example.com"} ]
 }`

then you can create two classes like this:

[Serializable]
private class ApiDataProfile {
     public string email;
}
[Serializable]
private class ApiData {
     public ApiDataProfile[] profiles;
}

These classes can be declared within the class which uses them. So you don't necessarily need to create new sourcecode files for them.

You can then create your JSON string by using object and collection initializers:

string data = JsonUtility.ToJson(
      new ApiData { 
         profiles = new ApiDataProfile[] {
             new ApiDataProfile { email = "email1@example.com" },
             new ApiDataProfile { email = "email2@example.com" }
         }
      }
); 

In some cases the API might expect keys which are not valid C# identifier names. They might start with a number or are reserved C# keywords and thus can not be used as variable names. In that case you can help yourself by using the @ character in front of them:

[Serializable]
private class EmailApiData {
     public string _email;
     public string @for;
     public int @1stLoginTimestamp;
}

public void SaveData() {
    string data = JsonUtility.ToJson(new EmailApiData() { 
         _email = email.text 
         @for = someOtherString
         @1stLoginTimestamp = DateTime.Now
    }); 
    //...
}
\$\endgroup\$
1
  • \$\begingroup\$ thank you so much! it works! thank you i will read up some more!! Had to make them public though and also changed the string data to new EmailApiProfileData() { email = field.text } \$\endgroup\$ – stratos la Mar 8 at 12:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.