I have a problem, where Json data is taken from server and then called out, but always outputs NULL. You can test code if you want to, Url is public.
This is Json data that I get from server
[{"id":"3","question":"Cik ir 4 + 4 = ?","answer1":"3","answer2":"13","answer3":"7","answer4c":"8"}]
How do I fix this, so Json data outputs correctly?
Thank you.
using System.Collections;
using System.Collections.Generic;
using System.Net.Mime;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System;
public class Code : MonoBehaviour
{
public Text first;
public const string URLBase = "http://91.200.67.104:8080/test/json.php";
[System.Serializable]
public class Results
{
public string id;
public string question;
public string answer1;
public string answer2;
public string answer3;
public string answer4c;
}
void Start()
{
StartCoroutine(Run());
}
IEnumerator Run()
{
var req = CreateReturnPlayerDataRequest();
yield return req.SendWebRequest();
var results = HandleReturnPlayerDataRequest(req);
first.text = results.id + " dasdasdas " + results.question;
}
public static UnityWebRequest CreateReturnPlayerDataRequest()
{
var req = UnityWebRequest.Get(URLBase);
return req;
}
public static Results HandleReturnPlayerDataRequest(UnityWebRequest req)
{
if (req.isNetworkError)
{
Debug.LogError("Failed to POST /player/register");
return new Results();
}
// Debug izvada datus console
Debug.Log("{\"Results\":" + req.downloadHandler.text + "}");
Results results = JsonUtility.FromJson<Results>("{\"Results\":" + req.downloadHandler.text + "}");
Debug.Log("ID:" + results.id + " ;question: " + results.question + " ; " + results.answer1);
Debug.Log(results.id);
Debug.Log(results.question);
Debug.Log(results.answer1);
return results;
}
}
Your deserialization class structure is incorrect.
Firstly, the json data you are receiving from the server is an array/collection (it is surrounded by square brackets "[ ]").
Secondly, you are placing it in the "Results" field of a parent object.
Therefore, this would be the correct structure:
[System.Serializable]
public class RootObject
{
public List<Results> Results;
}
[System.Serializable]
public class Results
{
public string id;
public string question;
public string answer1;
public string answer2;
public string answer3;
public string answer4c;
}
Usage:
var obj = JsonUtility.FromJson<RootObject>("{\"Results\":" + req.downloadHandler.text + "}");
Results serverData = obj.Results[0];
Related
I am developing a game for mobile and can't create a normal save system because when playing on the phone the error is logged: Could not find the file.
I use the persistent data path as it was recommended in many answers and this method works well in Editor and Windows but not in Android.
Is there something I can do about it? Additional info: I am using IL2CPP as backend. Heard that it might create problem with serialization.
Full code:
using System;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
public class JsonFileWriter : MonoBehaviour
{
public string path;
public JsonData data;
string jsonDataString;
void Awake(){
path = Path.Combine(Application.persistentDataPath, "savegames", "data.json");
FileInfo file = new FileInfo(path);
if(!Directory.Exists(path)){
file.Directory.Create();
}
CheckFileExistance(path);
DeserializeData();
SerializeData();
}
public void SerializeData()
{
CheckFileExistance(path);
jsonDataString = JsonUtility.ToJson(data, true);
File.WriteAllText(path, jsonDataString);
Debug.Log("JSon data "+ jsonDataString);
}
public void DeserializeData()
{
string loadedJsonDataString = File.ReadAllText(path);
data = JsonUtility.FromJson<JsonData>(loadedJsonDataString);
Debug.Log("health: " + data.healthBoostAmt.ToString() + "secondChar: " + data.secondCharacterUnlocked.ToString());
}
public void WriteData(int hp,int money,int score,int damage, bool secondChar,int moneyAmt,int charSelected){
data = new JsonData(hp,money,score,damage,secondChar,moneyAmt,charSelected);
SerializeData();
}
#region Getters and seters
public int GetHealthBoosterAmt(){
DeserializeData();
return data.healthBoostAmt;
}
public int GetMoneyBoosterAmt(){
DeserializeData();
return data.moneyBoostAmt;
}
public int GetScoreBoostAmt(){
DeserializeData();
return data.scoreBoostAmt;
}
public int GetDamageBoostAmt(){
DeserializeData();
return data.damageBoostAmt;
}
public bool GetSecondCharBought(){
DeserializeData();
return data.secondCharacterUnlocked;
}
public int GetMoneyAmt(){
DeserializeData();
return data.moneyAmt;
}
public int GetSelectedCharID(){
DeserializeData();
return data.charSelected;
}
public string GetJsonDataString(){
return jsonDataString;
}
public void SetJsonDataString(string newValue){
//int hp,int money,int score,int damage, bool secondChar
data = JsonUtility.FromJson<JsonData>(newValue);
WriteData(data.healthBoostAmt,data.moneyBoostAmt,data.scoreBoostAmt,data.damageBoostAmt,data.secondCharacterUnlocked,data.moneyAmt,data.charSelected);
}
#endregion
void CheckFileExistance(string filePath){
if (!File.Exists(filePath)){
File.Create(filePath).Close();
}
}
}
[Serializable]
public class JsonData
{
public int healthBoostAmt;
public int moneyBoostAmt;
public int scoreBoostAmt;
public int damageBoostAmt;
public bool secondCharacterUnlocked;
public int moneyAmt;
public int charSelected;
public JsonData (int healthBoostAmt,int moneyBoostAmt,int scoreBoostAmt,int damageBoostAmt,bool secondCharacterUnlocked,int moneyAmt,int charSelected)
{
this.healthBoostAmt = healthBoostAmt;
this.moneyBoostAmt = moneyBoostAmt;
this.scoreBoostAmt = scoreBoostAmt;
this.damageBoostAmt = damageBoostAmt;
this.secondCharacterUnlocked = secondCharacterUnlocked;
this.moneyAmt = moneyAmt;
this.charSelected = charSelected;
}
public JsonData (){}
}
I try to work inside Unity scripts with JSON datas from a SQL table. I'm using PHP to communicate with Unity.
Here is my PHP script:
<?php
try
{
$bdd = new PDO('mysql:host=xxx.mysql.db;dbname=xxx;charset=utf8', 'xxx', 'xxx');
}
catch(Exception $e)
{
die('Erreur : '.$e->getMessage());
}
$Wallet_Number = $_GET['Wallet_Number'];
$req = $bdd->prepare('SELECT Wallet_Number, NFT, Montant_Mise, Date_Spin FROM Wallets_Bets WHERE Wallet_Number = ?');
$req->execute(array($_GET['Wallet_Number']));
$req->setFetchMode(PDO::FETCH_ASSOC);
$json['Wallet_Number'] = $req->fetchAll();
$json['content'] = count($json['Wallet_Number']);
echo json_encode($json);
?>
The script is working fine, here is a result from a request:
{"Wallet_Number":[{"Wallet_Number":"XXX","NFT":"RetourFutur","Montant_Mise":"0","Date_Spin":"06\/04\/2022"},{"Wallet_Number":"XXX","NFT":"RetourFutur","Montant_Mise":"0","Date_Spin":"06\/04\/2022"},{"Wallet_Number":"XXX","NFT":"RetourFutur","Montant_Mise":"0,010000","Date_Spin":"06\/04\/2022"},{"Wallet_Number":"XXX","NFT":"RetourFutur","Montant_Mise":"0,01","Date_Spin":"06\/04\/2022"},{"Wallet_Number":"XXX","NFT":"MenInBlack","Montant_Mise":"0,01","Date_Spin":"06\/04\/2022"},{"Wallet_Number":"XXX","NFT":"Shinning","Montant_Mise":"0,10","Date_Spin":"06\/04\/2022"}],"content":6}
Here is my Unity class to manage de datas:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
[System.Serializable]
public class OVHJsonObject
{
// Start is called before the first frame update
public string Wallet_Number;
public string NFT;
public string Montant_Mise;
public string Date_Spin;
}
And finaly the Unity script which manage the JSON datas:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;
using Newtonsoft.Json;
using SimpleJSON;
namespace AllArt.Solana.Example
{
public class NGetJSONData : MonoBehaviour
{
string queryURL = "https://xxx.fr/CheckWallet.php?Wallet_Number=";
public static string NPKey;
public string NValue;
public static OVHJsonObject[ ] Wallet_data = new OVHJsonObject[9] ;
void Start()
{
}
public void PopulateList() {
NPKey = SimpleWallet.instance.wallet.GetAccount(0).GetPublicKey;
Debug.Log (" NPKEY : " + NPKey);
StartCoroutine(GetRequest(queryURL + NPKey));
}
IEnumerator GetRequest(string uri)
{
using (UnityWebRequest webRequest = UnityWebRequest.Get(uri))
{
// Request and wait for the desired page.
yield return webRequest.SendWebRequest();
string[] pages = uri.Split('/');
int page = pages.Length - 1;
switch (webRequest.result)
{
case UnityWebRequest.Result.ConnectionError:
case UnityWebRequest.Result.DataProcessingError:
Debug.LogError(pages[page] + ": Error: " + webRequest.error);
break;
case UnityWebRequest.Result.ProtocolError:
Debug.LogError(pages[page] + ": HTTP Error: " + webRequest.error);
break;
case UnityWebRequest.Result.Success:
Debug.Log(pages[page] + ":\nReceived: " + webRequest.downloadHandler.text);
NValue = webRequest.downloadHandler.text;
Wallet_data[0] = JsonUtility.FromJson<OVHJsonObject>(NValue);
Debug.Log(" Wallet Name : "+ Wallet_data[0] .Wallet_Number);
break;
}
}
}
// Update is called once per frame
void Update()
{
}
}
}
}
When running, I get no error from Unity but the fowllowing line always send an empty value (no null but nothing inside)
Debug.Log(" Wallet Name : "+ Wallet_data[0] .Wallet_Number);
Do you know what I am missing ? It seems the JSON format from my PHP script is not recognize in my Unity script.
Thank you,
Type and json data you give to JsonUtility.FromJson (type, variable) are not compatible.
You have Wallet_Number and int in Json. Then you first have parse Wallet_Number and then reach other elements in Wallet_Number.
When I test with your json data this code worked:
[System.Serializable]
public class WalletData
{
// Start is called before the first frame update
public string Wallet_Number;
public string NFT;
public string Montant_Mise;
public string Date_Spin;
}
[System.Serializable]
public class WalletsData
{
public WalletData[] Wallet_Number;
public int content;
}
WalletsData wallets = JsonUtility.FromJson<WalletsData>(jsonData);
Debug.Log(wallets.Wallet_Number[0].Wallet_Number);
Is there a way to get rid of practise.AcademicProgram in the output when the display() is called for an object initialized by the parameterized constructor. In my code below this occurs when s2.Display(); is executed.
Below is my working code for the same:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace practise
{
public class AcademicProgram
{
//Memnber variables
private int programCode;
private string programName;
private int programCredits;
//Properties for reading and writting the values of private fields
public int ProgramCode { get => programCode; set => programCode = value; }
public string ProgramName { get => programName; set => programName = value; }
public int ProgramCredits { get => programCredits; set => programCredits = value; }
//Default Constructor
public AcademicProgram()
{
}
//Parameterized Constructor
public AcademicProgram (int programCode, string programName, int programCredits)
{
this.programCode = programCode;
this.programName = programName;
this.programCredits = programCredits;
}
public void DisplayResults()
{
Console.WriteLine("Program Code: {0}\nProgram Name: {1}\nProgram Credits: {2}\n", programCode, programName, programCredits);
Console.WriteLine();
}
}
public class Instructor
{
//Member variables
public string forename;
public string surname;
public int identificationNumber;
public AcademicProgram academicProgram;
//Default Constructor
public Instructor()
{
this.forename = string.Empty;
this.surname = string.Empty;
this.identificationNumber = 0;
this.academicProgram = null;
}
//Parameterized Constructor
public Instructor(string forename, string surname, int identificationNumber, AcademicProgram academicProgram)
{
this.forename = forename;
this.surname = surname;
this.identificationNumber = identificationNumber;
this.academicProgram = academicProgram;
}
// Member Function to display values of member variables on Console.
public void Display()
{
Console.WriteLine(this.forename + ", " + this.surname + ", " + this.identificationNumber + ", " + this.academicProgram);
Console.WriteLine();
}
//Driver function
static void Main(string[] args)
{
//Instantiating object to call non-static member method
Instructor p = new Instructor();
p.Go();
Console.ReadKey();
}
//Non-static Member function
public void Go()
{
//Instantiating object without passing any values on runtime.
Instructor s = new Instructor();
//Instantiating object of AcademicProgram class without passing any values on runtime.
AcademicProgram progName = new AcademicProgram ();
//Set the values of fields using properties
progName.ProgramCode = 8230;
progName.ProgramName = "Systems Development: Cocnepts and Analysis";
progName.ProgramCredits = 4;
// Instantiating object while providing values on runtime.
Instructor s2 = new Instructor("Eddie ", "Jessup", 2394589, progName);
//Call to display method
s.Display();
s2.Display();
progName.DisplayResults();
}
}
}
Which gives an output shown here
Aside from override ToString(), I was able to fix it by a simple fix in display() of Instructor class as below:
public void Display()
{
Console.WriteLine(this.forename + ", " + this.surname + ", " + this.identificationNumber + ", " + this.academicProgram.ProgramCode + ", " + this.academicProgram.ProgramName + ", " + this.academicProgram.ProgramCredits);
Console.WriteLine();
}
I'm making a quiz game and I'm stuck at this problem that is probably easy to do.
I have this script, which gets JSON data from server and separates it:
using System.Collections;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System;
using TMPro;
[Serializable]
public class RootObject
{
public Results[] Result;
}
[Serializable]
public class Results
{
public string id;
public string question;
public string answer1;
public string answer2;
public string answer3;
public string answer4c;
}
public class DataLoader : MonoBehaviour
{
public PickPlace pickplace;
public string URLBase;
public void GetQustion()
{
URLBase = pickplace.url;
StartCoroutine(Run());
}
IEnumerator Run()
{
var req = CreateReturnPlayerDataRequest();
yield return req.SendWebRequest();
var results = HandleReturnPlayerDataRequest(req);
// Izvada konsolē saņemtos datus
Debug.Log("Quesiton: " + results.Result[0].question + " Answer1: " + results.Result[0].answer1 + " Answer2: " + results.Result[0].answer2 + " Answer3: " + results.Result[0].answer3 + " Answer4: " + results.Result[0].answer4c);
}
public UnityWebRequest CreateReturnPlayerDataRequest()
{
var req = UnityWebRequest.Get(URLBase);
return req;
}
public static RootObject HandleReturnPlayerDataRequest(UnityWebRequest req)
{
if (req.isNetworkError)
{
Debug.LogError("Failed to POST /player/register");
return new RootObject();
}
var results = JsonUtility.FromJson<RootObject>("{\"Result\":" + req.downloadHandler.text + "}");
return results;
}
}
My question is:
How can I call out array in, for example my GameManager script and call out separated data, so that I can put for example question text from JSON data into Text object and all 4 answers to buttons?
Currently you have a method to start the request but you never wait until / will know when it is done!
I would simply use an Action<RootObject> as parameter so you can add a callback listener and react to the result when it is invoked.
public class DataLoader : MonoBehaviour
{
public PickPlace pickplace;
public string URLBase;
public void GetQuestions(Action<RootObject> onSuccess)
{
URLBase = pickplace.url;
StartCoroutine(Run(onSuccess));
}
IEnumerator Run(Action<RootObject> onSuccess)
{
var req = CreateReturnPlayerDataRequest();
yield return req.SendWebRequest();
var results = HandleReturnPlayerDataRequest(req);
if(results == null)
{
yield break;
}
Debug.Log("Quesiton: " + results.Result[0].question + " Answer1: " + results.Result[0].answer1 + " Answer2: " + results.Result[0].answer2 + " Answer3: " + results.Result[0].answer3 + " Answer4: " + results.Result[0].answer4c);
// Now invoke the Callback so whoever started the post call gets the results
onSuccess?.Invoke(results);
}
public UnityWebRequest CreateReturnPlayerDataRequest()
{
var req = UnityWebRequest.Get(URLBase);
return req;
}
private RootObject HandleReturnPlayerDataRequest(UnityWebRequest req)
{
if(req.isHttpError || req.isNetworkError)
{
Debug.LogError($"Failed to POST /player/register! Failed with {req.responseCode} - Reason: {req.error}");
onDone?.Invoke(null);
return null;
}
var results = JsonUtility.FromJson<RootObject>("{\"Result\":" + req.downloadHandler.text + "}");
return results;
}
}
So now you can call it from another class like e.g.
// Drag these in via the Inspector
[SerializeField] private DataLoader dataLoader;
[Space]
[SerializeField] private Text questionText;
[Space]
[SerializeField] private Text button1Text;
[SerializeField] private Text button2Text;
[SerializeField] private Text button3Text;
[SerializeField] private Text button3Text;
public void SomeMethod()
{
// Do the post call and react once the results are there either as lambda expression
dataLoader.GetQuestions(results => {
Debug.Log("Successfully received data. Will update GUI", this);
// do something with the results now e.g.
var first = results.Result[0];
questionText.text = first.question;
button1Text.text = first.answer1;
button2Text.text = first.answer2;
button3Text.text = first.answer3;
button4Text.text = first.answer4;
});
// alternatively you can do the same also using a method
dataLoader.GetQuestions(OnPostRequestFinished);
}
private void OnPostRequestFinished(RootObject results)
{
Debug.Log("Successfully received data. Will update GUI", this);
// do something with the results now e.g.
var first = results.Result[0];
questionText.text = first.question;
button1Text.text = first.answer1;
button2Text.text = first.answer2;
button3Text.text = first.answer3;
button4Text.text = first.answer4;
}
I'm using PHP and Unity to make a simple game, and when I request dates with php, but I callback this error "ArgumentException: JSON must represent an object type."
json:
[{"id":"1","user_id":"1","nome":"Conde","level":"1","hp":"100","mana":"100","stamina":"100","dano":"35","vel_atq":"35","defesa":"35","bloqueio":"35","critico":"35","dano_critico":"35"}]
C# Unity
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System;
public class PlayerS2 : MonoBehaviour
{
public string url = "http://localhost/";
[Serializable]
public class MyPlayer
{
public int user_id;
public string nome;
public int level;
public int hp;
public int mana;
public int stamina;
public int dano;
public float vel_atq;
public int defesa;
public int bloqueio;
public int critico;
public int dano_critico;
}
public IEnumerator GetDadosPlayer(string userID)
{
MyPlayer dadosPlayer = new MyPlayer();
WWWForm form = new WWWForm();
form.AddField("userID", userID);
using (UnityWebRequest www = UnityWebRequest.Post(url + "GetDadosPlayer.php", form))
{
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
{
Debug.Log(www.error);
}
else
{
Debug.Log(www.downloadHandler.text);
string json = www.downloadHandler.text;
dadosPlayer = JsonUtility.FromJson<MyPlayer>(json);
Debug.Log(dadosPlayer.nome);
}
}
}
void Start(){
StartCoroutine(GetDadosPlayer("1"));
}
}
PHP
<?php
require_once("ConexaoBD.php");
$userID = isset($_POST['userID']) ? $_POST['userID'] : "1";
$query = '
SELECT
*
FROM
player
WHERE
user_id = :user_id
';
$stmt = $conn->prepare($query);
$stmt->bindValue(':user_id',$userID);
$stmt->execute();/*
$result = $stmt->fetchAll(PDO::FETCH_OBJ);
if(!empty($result)){
echo "";
}else{
echo $result[0]->$id;
}
*/
$results;
while($result = $stmt->fetchAll(PDO::FETCH_OBJ)){
$results = $result;
}
echo json_encode($results);
?>
You're trying to cast a one-object array as an object.
The square brackets around your JSON represents an array. The curly brackets represent your object. This line:
dadosPlayer = JsonUtility.FromJson<MyPlayer>(json);
...tries to take your JSON and turn it into a MyPlayer object, but your JSON doesn't represent an object, it represents an array of objects.
The code that is pulling your object out of the database using "fetchAll" is designed to return multiple objects and put them into an array. Since your code should only ever return one object from the database, instead of fetchAll, try to find a function that only returns one object from the database.
The object it should return should look like this:
{"id":"1","user_id":"1","nome":"Conde","level":"1","hp":"100","mana":"100","stamina":"100","dano":"35","vel_atq":"35","defesa":"35","bloqueio":"35","critico":"35","dano_critico":"35"}
not like this:
[{"id":"1","user_id":"1","nome":"Conde","level":"1","hp":"100","mana":"100","stamina":"100","dano":"35","vel_atq":"35","defesa":"35","bloqueio":"35","critico":"35","dano_critico":"35"}]