1

Ok so basically I am trying to get the hang of de-serializing and serializing custom classes in C# (unity) from strings. Json seemed to be the obvious method and is usable with mysql which I plan to use to store player data.

I can't get past a test string example I am trying to run to make a "Dummy" playerdata object. From there I will pass the player object to an Initialize method on the player at login.

Again I am just trying to use a (dummy) string (Which is the results of mysql queries right?) to generate a player data object. This is what I have.

PlayerData.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

[System.Serializable]
public class PlayerData
{
    public string Name {get; protected set;}
    public uint Attack {get; protected set;}
    public uint Defense {get; protected set;}
    public uint Armor {get; protected set;}
    public uint MovementSpeed {get; protected set;}
    public uint MagicLevel {get; protected set;}

    public static PlayerData Serialize(string obj)
    {
      return JsonUtility.FromJson<PlayerData>(obj);
    }
}

the code I use to run it is this:

String test = @"{
    ""Name"": ""Chase"",
    ""Attack"" : 50,
    ""Defense"" : 35,
    ""Armor"" : 12,
    ""MovementSpeed"" : 60,
    ""MagicLevel"" : 15,
}";
PlayerData data = PlayerData.Serialize(test);
Debug.Log(data.Attack);

The error I get is this.

ArgumentException: JSON parse error: Missing a name for object member.

I really need help here, I have tried to ecapsulate the int variables with the double quotation marks, tried to do the same with all values, hell I have tried it so many ways, each time either that error or invalid value. Please any help would be much appreciated.

maccettura
  • 10,514
  • 3
  • 28
  • 35
  • Why are you creating strings on your own instead of serializing an existing object? Also, you have the wording backwards. Serialize means `object -> json`, deserialiing is `json -> object` – maccettura May 02 '18 at 20:27
  • The plan is to build a string from queries to mysql to collect the data, then pass that string to the playerdata class's static method to generate and instance of playerdata with the data provided from the queries. So I won't have actualy JSON files, just values pulled from a database. – Codinablack May 02 '18 at 20:30
  • You should not be building strings, the whole point of serialization/deserialization is to work with objects. You can gather the values you need from MySql, but you need to add those values to an object, and then serialize that object to get the JSON. – maccettura May 02 '18 at 20:31
  • I am deserializing, i just named my method incorrectly. I have the JSON in string format, I want to turn it into an object. json -> object... deserializing. – Codinablack May 02 '18 at 20:31
  • I can tell from the code you were deserializing, I just wanted you to be aware that it shouldnt be called `Serialize()`. Don't worry, I understood – maccettura May 02 '18 at 20:32
  • Ok so I get what you are saying, I am only doing half the work, the json is never serialized. thus it can't be deserialized? – Codinablack May 02 '18 at 20:33
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/170246/discussion-between-maccettura-and-codinablack). – maccettura May 02 '18 at 20:34
  • This is the reference I was trying to build up from. https://docs.unity3d.com/ScriptReference/JsonUtility.FromJson.html – Codinablack May 02 '18 at 20:35
  • **1**. Remove `{get; protected set;}` from the variables in `PlayerData`. Unity cannot serialize/de-serialize properties. **2**. Your json is not valid. Do not create json by hand if you are not sure how to create json. Generate the json by code. You can do this by creating instance of `PlayerData`, initialize it with values you want then convert it to json with `JsonUtility.ToJson`. This will give you a valid you will be using to test deserializing. To use that json in a code, use [this](https://www.freeformatter.com/java-dotnet-escape.html#ad-output) to escape it first. – Programmer May 02 '18 at 23:07
  • If you still have issues, see *4.TROUBLESHOOTING JsonUtility:* from the duplicate. – Programmer May 02 '18 at 23:07

1 Answers1

1

You have two issues. The first one is Unity does not like your trailing comma after MagicLevel. Remove that:

String test = @"{
    ""Name"": ""Chase"",
    ""Attack"" : 50,
    ""Defense"" : 35,
    ""Armor"" : 12,
    ""MovementSpeed"" : 60,
    ""MagicLevel"" : 15
}";

Second you are having issues because your properties have a protected set. This means Unity can never assign those values because JsonUtility.FromJson() is not your PlayerData class or a class that inherits from it so it does not have the access to set those properties.

I understand that you want to keep these properties from being set by anything other than the serialization (or later a constructor). To do that in unity specifically, you need the [SerializeField] attribute:

[System.Serializable]
public class PlayerData
{
    [SerializeField]
    protected string _name 
    
    public string Name {get { return _name;}}

    [SerializeField]
    protected uint _attack;
    
    public uint Attack {get { return _attack;}}

    [SerializeField]
    protected uint _defense;
    
    public uint Defense {get { return _defense;}}

    [SerializeField]
    protected uint _armor;
    
    public uint Armor {get { return _armor;}}

    [SerializeField]
    protected uint _movementSpeed;
    
    public uint MovementSpeed {get { return _movementSpeed;}}

    [SerializeField]
    protected uint _magicLevel;
    
    public uint MagicLevel {get { return _magicLevel;}}

    public static PlayerData Deserialize(string obj)
    {
        return JsonUtility.FromJson<PlayerData>(obj);
    }
}

I went and renamed your Serialize() method to Deserialize() because that's what its actually doing.

Edit

Based on your trial and error it seems that Unity takes issue with serializing properties. Which is unfortunate because properties are the prefered way to handle setting and getting of data in an object. I have edited my example code to reflect protected fields with public properties

Community
  • 1
  • 1
maccettura
  • 10,514
  • 3
  • 28
  • 35
  • Damn man I was so hopeful, but it didn't work. Same exact error. ArgumentException: JSON parse error: Missing a name for object member. – Codinablack May 02 '18 at 21:03
  • Serialize field just makes it visible in the editor. Doesn't do anything else. – Codinablack May 02 '18 at 21:04
  • @Codinablack it also serializes the private property when you perform serialization. – maccettura May 02 '18 at 21:05
  • @Codinablack can you post the exact JSON you are using if its different from what you included in your question – maccettura May 02 '18 at 21:05
  • Tried removing all the protected keywords, still same result. – Codinablack May 02 '18 at 21:07
  • @Codinablack then there has to be something wrong with your json. The json you included in your question seems valid, but if thats the exact same json you are using maybe try removing the trailing comma after `MagicLevel` – maccettura May 02 '18 at 21:08
  • What is in my question is exact, copy and paste, plus added spaces to the front from formatting. – Codinablack May 02 '18 at 21:08
  • Ok! Error is gone! However the data returned in the debug is incorrect. It returns 0, still using without protected keywords – Codinablack May 02 '18 at 21:09
  • @Codinablack are the `protected set`'s back in? Try using the `[SerializeField]` with the `protected set` and I think that will do the trick – maccettura May 02 '18 at 21:10
  • Nope. However I was able to figure it out. Apparently it doesn't work with the properties period. Now I just gotta try to use protected or private fields and public properties. Thanks for all your help man. I think I will post the finished working version when I get it right. – Codinablack May 02 '18 at 21:14
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/170249/discussion-between-codinablack-and-maccettura). – Codinablack May 02 '18 at 21:20
  • Protected, or private fields don't work either... Maybe I shouldn't use unity's method... – Codinablack May 02 '18 at 21:22
  • @Codinablack protected or private fields will work with that attribute `SerializeField` – maccettura May 02 '18 at 21:23