C
C#•4d ago
Ras Gulla

Newtonsoft Json not deserializing with some property/constructor names

Hi, I'm using newtonsoft json to serialize and deserialize my classes. Everything works perfect until I put the name ID, Identifier, UniqueIdentifier anywhere in my class or Constructor which is to be deserialized. For example:
public class Command
{
public string UniqueID { get; set; }
public float PositionX { get; set; }
public float PositionY { get; set; }
public float PositionZ { get; set; }

public Command(string id, Vector3 position)
{
PositionX = position.x;
PositionY = position.y;
PositionZ = position.z;

UniqueID = id;
}
}
public class Command
{
public string UniqueID { get; set; }
public float PositionX { get; set; }
public float PositionY { get; set; }
public float PositionZ { get; set; }

public Command(string id, Vector3 position)
{
PositionX = position.x;
PositionY = position.y;
PositionZ = position.z;

UniqueID = id;
}
}
This serializes perfectly but when I try to deserialize it, the Identifier is null. If I change the name to something else, for example key It will work and deserialize perfectly... Anyone knows the reason for it? Here's what I receive and try to deserialize:
{
"PositionX":7.63098526,
"PositionY":15.25,
"PositionZ":12.0,
"RotationX":0.0,
"RotationY":0.0,
"RotationZ":0.0,
"RotationW":1.0,
"UniqueID":"40dd0008-bc4c-4988-a9f9-835f6a0c2ac9"
}
{
"PositionX":7.63098526,
"PositionY":15.25,
"PositionZ":12.0,
"RotationX":0.0,
"RotationY":0.0,
"RotationZ":0.0,
"RotationW":1.0,
"UniqueID":"40dd0008-bc4c-4988-a9f9-835f6a0c2ac9"
}
And here's how I'm deserializing it:
public static T Deserialize(string json)
{
try
{
if (string.IsNullOrEmpty(json))
{
Debug.LogError("Cannot deserialize null or empty JSON.");
return null;
}

return JsonConvert.DeserializeObject<T>(json);
}
catch (Exception ex)
{
Debug.LogError($"Deserialization failed: {ex.Message}");
return null;
}
}
public static T Deserialize(string json)
{
try
{
if (string.IsNullOrEmpty(json))
{
Debug.LogError("Cannot deserialize null or empty JSON.");
return null;
}

return JsonConvert.DeserializeObject<T>(json);
}
catch (Exception ex)
{
Debug.LogError($"Deserialization failed: {ex.Message}");
return null;
}
}
If anyone have any good explanation for it, please let me know.
29 Replies
Keswiik
Keswiik•4d ago
probably need a default constructor for newtonsoft to use
Ras Gulla
Ras GullaOP•4d ago
Any specific explanation for it? Since position and rotation is perfectly deserialized just that id is null...
Angius
Angius•4d ago
Any particular reason you're using Newtonsoft in the first place, btw?
Ras Gulla
Ras GullaOP•4d ago
To Serialize and Deserialize for sending over the network... 🤔
Angius
Angius•4d ago
Yeah, but .NET has built-in Json serialization now Unless you're using an old version of the framework or something
Ras Gulla
Ras GullaOP•4d ago
I can't change it now, I've published 13 Minigames with this, changing it now would be a headache
Angius
Angius•4d ago
Ah, it's Unity?
Ras Gulla
Ras GullaOP•4d ago
Yes
Angius
Angius•4d ago
Then it falls under "old version of the framework" Carry on
Ras Gulla
Ras GullaOP•4d ago
😅
Pobiega
Pobiega•4d ago
Your constructor parameters are named differently from your properties, and there is no parameterless constructor
Adam Vincent
Adam Vincent•4d ago
yup, serializers like System.Text.Json and JSON.Net are looking for a public parameter-less constructor https://stackoverflow.com/questions/23017716/json-net-how-to-deserialize-without-using-the-default-constructor
Stack Overflow
JSON.net: how to deserialize without using the default constructor?
I have a class that has a default constructor and also an overloaded constructor that takes in a set of parameters. These parameters match to fields on the object and are assigned on construction....
Ras Gulla
Ras GullaOP•4d ago
So just adding a empty constructor would fix the problem? What about position, rotation? They are being deserialized as intended...
Pobiega
Pobiega•4d ago
respectfully, that aint true
public class Command
{
public string UniqueID { get; set; }
public float PositionX { get; set; }
public float PositionY { get; set; }
public float PositionZ { get; set; }

public Command(string id, Vector3 position)
{
PositionX = position.x;
PositionY = position.y;
PositionZ = position.z;

UniqueID = id;
}
}
public class Command
{
public string UniqueID { get; set; }
public float PositionX { get; set; }
public float PositionY { get; set; }
public float PositionZ { get; set; }

public Command(string id, Vector3 position)
{
PositionX = position.x;
PositionY = position.y;
PositionZ = position.z;

UniqueID = id;
}
}
there are no properties or fields here for rotation so it cant possibly deserialize properly
Ras Gulla
Ras GullaOP•4d ago
It was an example I just write in Discord, Lemme show the actual class:
Pobiega
Pobiega•4d ago
assuming all your properties have public setters, it should be fine with a blank parameterless constructor, yes
Ras Gulla
Ras GullaOP•4d ago
public class TrashUpdateCommand : BaseCommand<TrashUpdateCommand>
{
public float PositionX { get; set; }
public float PositionY { get; set; }
public float PositionZ { get; set; }

public float RotationX { get; set; }
public float RotationY { get; set; }
public float RotationZ { get; set; }
public float RotationW { get; set; }

public string Key { get; private set; }

public TrashUpdateCommand(string Key, Vector3 position, Quaternion rotation)
{
this.Key = Key;

PositionX = position.x;
PositionY = position.y;
PositionZ = position.z;

RotationX = rotation.x;
RotationY = rotation.y;
RotationZ = rotation.z;
RotationW = rotation.w;
}
public Vector3 GetPosition()
{
return new Vector3(PositionX, PositionY, PositionZ);
}
public Quaternion GetRotation()
{
return new Quaternion(RotationX, RotationY, RotationZ, RotationW);
}
}
public class TrashUpdateCommand : BaseCommand<TrashUpdateCommand>
{
public float PositionX { get; set; }
public float PositionY { get; set; }
public float PositionZ { get; set; }

public float RotationX { get; set; }
public float RotationY { get; set; }
public float RotationZ { get; set; }
public float RotationW { get; set; }

public string Key { get; private set; }

public TrashUpdateCommand(string Key, Vector3 position, Quaternion rotation)
{
this.Key = Key;

PositionX = position.x;
PositionY = position.y;
PositionZ = position.z;

RotationX = rotation.x;
RotationY = rotation.y;
RotationZ = rotation.z;
RotationW = rotation.w;
}
public Vector3 GetPosition()
{
return new Vector3(PositionX, PositionY, PositionZ);
}
public Quaternion GetRotation()
{
return new Quaternion(RotationX, RotationY, RotationZ, RotationW);
}
}
Adam Vincent
Adam Vincent•4d ago
or you can specify the constructor with the JsonConstructorAttribute
Ras Gulla
Ras GullaOP•4d ago
I've changed the name to key here because it was working 😅 I was actually trying to find the answer for this behaviour. I didn't find any answer for it on google that if we name our properties like this, it won't work.
Adam Vincent
Adam Vincent•4d ago
If you changed
public string Key { get; private set; }
public string Key { get; private set; }
to
public string key { get; private set; } //lower case property name
public string key { get; private set; } //lower case property name
then you might be looking for CamelCasePropertyNamesContractResolver
Pobiega
Pobiega•4d ago
private set isnt the same as set thats why Key isnt deserializing properly if it worked, its because your constructor takes a key parameter and newtonsoft figures out that probably maps to the Key property
Ras Gulla
Ras GullaOP•4d ago
Hmmm, I'll try this. I guess I tried it with public setter too. I'll come again with more data : )
Adam Vincent
Adam Vincent•4d ago
If you have a really good reason why Key is private set you can use PrivateSetterContractResolver(), to deserilize privates
Pobiega
Pobiega•4d ago
with a public setter and a parameterless constructor, I see no reason why this shouldnt work
Ras Gulla
Ras GullaOP•4d ago
No, don't have any reason for it. I guess I Just accidently set it private while I was trying different things to find any answer
Adam Vincent
Adam Vincent•4d ago
been there. Auto-complete will do that to ya.
Ras Gulla
Ras GullaOP•4d ago
Yeah : ) I'll try it again. I'm sure it didn't work with public setter too. Will come here after confirming 🙂 Anyways, Thank You!
Honza K.
Honza K.•4d ago
IMO all you had to do was place [JsonProperty("UniqueID")] on the constructor id parameter 😄
Ras Gulla
Ras GullaOP•4d ago
Could workaround but wanted to know "Why" 😅 Guys I just confirmed, it was an issue with constructor and had nothing to do with name as I was thinking. This worked perfectly fine:
public class TestCommand : BaseCommand<TestCommand>
{
public string ID { get; set; }
public int UniqueID { get; set; }
public int SomeNumber { get; set; }

public TestCommand(int number, int uid, string id)
{
ID = id;
UniqueID = uid;
SomeNumber = number;
}
}
public class TestCommand : BaseCommand<TestCommand>
{
public string ID { get; set; }
public int UniqueID { get; set; }
public int SomeNumber { get; set; }

public TestCommand(int number, int uid, string id)
{
ID = id;
UniqueID = uid;
SomeNumber = number;
}
}
Thank You so much 🫶

Did you find this page helpful?