سؤال

Alright. I'm working on a save editor for a game as a project and the save is in JSON. I have a small snippet returned from the actual editor after using it, and it looks like:

{"hero":{"STR":10,"HP":33,"HT":35,"attackSkill"13,"defenseSkill":3}}

This is only a small part of the save. I can't for the life of me figure out how to only replace this part in the whole save. I have tried

  • Json to C#-ing the whole thing. This doesn't work because for some reason the game maker decided to have half of the fields be class names from his game, ex. "com.whatever.whatever":1. This freaks out the parser.
  • Just using the returned snippet. The game won't accept it as it's not nearly as complete as the actual save.
  • Just searching for the values. I can't get this to work, just because I don't how to manipulate strings well.

I want to just replace the

{"hero"{...}} 

part with the new part.

How would I go about doing it? Thanks.

Also, pastebin of the game save, if anyone wants/needs it: http://pastebin.com/eK13cNtg

هل كانت مفيدة؟

المحلول

Json.NET supports "LINQ to JSON" and dynamic access which allows the entire tree to be dealt with dynamically without need for a POCO mapping. This has the advantage over deserializing to typed objects in that additions to the mapping do not need to be accounted for round-trip serialization.

This can be used to parse the JSON, modify the object structure, and then rebuild the JSON text.

Such an approach might look like the following, or it could use one of the other query methods available. (I didn't look much into the actual JSON - eww, btw! - but the query structure should be readily visible after pretty-printing it as appropriate.)

JObject data = JObject.Parse(json);
JObject hero = (JObject)data["hero"];
hero["STR"] = 42;        // "god-like strength" hax; modifies the JObject
json = data.ToString();  // re-serialize tree, along with modifications

The dynamic type can also be used for access and manipulation of a Json.NET tree.


Json.NET can work perfectly fine with "odd names", but such names need to be specified with annotations or mapped to a type with dynamic keys such as a Dictionary/JObject.

However, I would not use a POCO route here due to the wide range of names used - it would be stupidly hard/tedious to codify everything into fully early-bound types; that is not to say, however, that the "hero" couldn't be parsed into a specific POCO.

نصائح أخرى

I am not a C# guy, but I would see if there is a different parser. The internal periods are unfortunate, but provided they are inside quoted strings (and its not real JSON if they are not) the parser should be able to handle it as they are valid JSON (because they are valid Javascript).

The following Javascript

var myObj = {'no.kidding':'This is valid'};
alert(myObj['no.kidding']);

Will in fact alert you that "This is valid".

If the parser you are using doesn't support it, I'd say its not a compliant parser.

You can find parsers by language here: http://json.org/ - it looks like about a dozen for C#, so hopefully one of them will work for you.

An ugly hack (but possibly serviceable solution) if you don't have any floating point numbers which would be screwed up would be to do global replace of '.' for '_' (or some other non-problematic token) before parsing and then reverse it when you re-stringify it. You could also use a regex of some sort to only replace the periods if they are inside of quoted strings, which would protect you a bit on the numbers issue.

Json to C#-ing the whole thing. This doesn't work because for some reason the game maker decided to have half of the fields be class names from his game, ex. "com.whatever.whatever":1. This freaks out the parser.

I could not recreate the issue. This works for me.

dynamic response = Newtonsoft.Json.Linq.JObject.Parse(json);
var jsonNewHero = "{'hero':{'STR':10,'HP':33,'HT':35,'attackSkill': 13,'defenseSkill':3}}";
dynamic newHero = Newtonsoft.Json.Linq.JObject.Parse(jsonNewHero);
response.hero = newHero.hero;
var newJson = Newtonsoft.Json.JsonConvert.SerializeObject(response, Newtonsoft.Json.Formatting.Indented);

Working .NET Fiddle: http://dotnetfiddle.net/PKPQC1

P.S: Using the latest Newtonsoft Json version 6.0.1

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top