Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Same object got serialized twice in the object graph #200

Closed
ekolis opened this issue Jan 31, 2014 · 7 comments
Closed

Same object got serialized twice in the object graph #200

ekolis opened this issue Jan 31, 2014 · 7 comments

Comments

@ekolis
Copy link

ekolis commented Jan 31, 2014

Once here:

"PrimaryRace": {
"$id": "22277",
"$type": "FrEee.Game.Objects.Civilization.Race, FrEee.Core",
"Name": "Random Race #2",
"PopulationIconName": null,
"NativeAtmosphere": "Methane",
"NativeSurface": "Ice",
"HappinessModelName": null,
"TraitNames": {
"$id": "22278",
"$type": "System.Collections.Generic.List1[[System.String, mscorlib]], mscorlib", "$values": [] }, "Aptitudes": { "$id": "22279", "$type": "FrEee.Utility.SafeDictionary2[[System.String, mscorlib],[System.Int32, mscorlib]], FrEee.Core",
"Physical Strength": 100,
"Intelligence": 100,
"Cunning": 100,
"Environmental Resistance": 100,
"Reproduction": 100,
"Happiness": 100,
"Aggressiveness": 100,
"Defensiveness": 100,
"Political Savvy": 100,
"Mining Aptitude": 100,
"Farming Aptitude": 100,
"Refining Aptitude": 100,
"Construction Aptitude": 100,
"Repair Aptitude": 100,
"Maintenance Aptitude": 100
},
"ID": 5212045564066541657,
"IsDisposed": false
},

And once here:

"Key": {
"$id": "22277",
"$type": "FrEee.Game.Objects.Civilization.Race, FrEee.Core",
"Name": "Random Race #2",
"PopulationIconName": null,
"NativeAtmosphere": "Methane",
"NativeSurface": "Ice",
"HappinessModelName": null,
"TraitNames": {
"$ref": "22278"
},
"Aptitudes": {
"$ref": "22279"
},
"ID": 5212045564066541657,
"IsDisposed": false
},

This is causing a crash on deserialization, because the object is defined twice. The sub-objects referenced by this object are being serialized properly, but the object itself is not.

I did do something special with this object to get it to deserialize in the first place - it was originally a key in a dictionary, but since JSON.NET doesn't support complex types for dictionary keys, I wrote a wrapper property, and marked the original dictionary property non-serializable:

/// <summary>
/// For serialization, since JSON.NET can't handle dictionary keys of complex types.
/// </summary>
public List<KeyValuePair<Race, long>> PopulationList
{
    get
    {
        return Population.ToList();
    }
    set
    {
        Population.Clear();
        foreach (var kvp in value)
            Population.Add(kvp);
    }
}
@ekolis
Copy link
Author

ekolis commented Jan 31, 2014

I was able to work around this by changing the wrapper property:

/// <summary>
/// For serialization, since JSON.NET can't handle dictionary keys of complex types.
/// </summary>
public ISet<Tuple<Race, long>> PopulationList
{
    get
    {
        return new HashSet<Tuple<Race, long>>(Population.Select(kvp => Tuple.Create(kvp.Key, kvp.Value)));
    }
    set
    {
        Population.Clear();
        foreach (var t in value)
            Population.Add(t.Item1, t.Item2);
    }
}

@ekolis
Copy link
Author

ekolis commented Jan 31, 2014

Well, not quite. The wrapper property isn't being serialized either now! Or rather, the tuples aren't... guess I'll need a custom type!

@ekolis
Copy link
Author

ekolis commented Jan 31, 2014

Yeah, I was filtering out read-only properties, and since tuples are immutable...

@ekolis
Copy link
Author

ekolis commented Jan 31, 2014

Nope, even a custom type didn't work. It appears that JSON.NET, when deserializing a property, first constructs a blank object, then assigns it to the property, then manipulates the property value. Which is completely useless if the property in question is a throwaway proxy for the real property, because this means that any changes that JSON.NET makes are thrown away! Maybe that's what type converters are for?

@ekolis
Copy link
Author

ekolis commented Jan 31, 2014

This seems to be a bug with KeyValuePairs, because when I annotate my dictionary type with [JsonArray], I get the same duplicate-object problem. Perhaps this is because KeyValuePairs are structs?

@JamesNK
Copy link
Owner

JamesNK commented Feb 23, 2014

ObjectCreationHandling.Replace

@JamesNK JamesNK closed this as completed Feb 23, 2014
@ekolis
Copy link
Author

ekolis commented Apr 22, 2014

Got a chance to look at this again, and no, this didn't help. The problem might be that the two references to my object are in two different dictionaries. So ObjectCreationHandling.Replace doesn't know that the other reference exists, perhaps?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants