Converting JSON to list of dictionaries - c#

I'm working on a Unity (C#) project and trying to convert JSON data from an API to a list of dictionaries. I'm trying to use Unity's JSONSerialization, but I'm not sure what to do.
In the documentation, it says the following, and I was wondering if anyone could guide me to how I can convert the JSON? Sorry for the easy question as I'm new to C# and in the other languages I use like Javascript/Python, this is quite easily done.
Passing other types directly to the API, for example primitive types
or arrays, is not currently supported. For now you will need to wrap
such types in a class or struct of some sort.
https://docs.unity3d.com/Manual/JSONSerialization.html
The JSON returned is as follows and is a list of dictionaries, and each dictionary has two keys (_id and firstName).
[{"_id":"xxx", "firstName":"Brayann"}, {"_id":"yyy", "firstName":"Peter"}]

Create object in which you will Deserialize the json. Call ToDictionary after that.
Full example: dotNetFiddle
public static void Main(string[] args)
{
string json = #"[{ ""_id"":""xxx"", ""firstName"":""Brayann""}, { ""_id"":""yyy"", ""firstName"":""Peter""}]";
var result = JsonConvert.DeserializeObject<List<RootListObject>>(json)
.ToDictionary(x=> x.id, y=> y.firstName);
}
public class RootListObject
{
[JsonProperty(PropertyName ="_id")]
public string id { get; set; }
public string firstName { get; set; }
}

As far as I know you can't deserialize as enumarable of dictionary but you can create a class for this purpose which is more reasonable:
public class SomeDataType
{
public string _id { get; set; }
public string firstName { get; set; }
}
Then you can deserialize as List<SomeDataType>.
Even if you really require the dictionary you can add a ToDictionary method to your class.

Related

Serialize and deserialize Json property to two different values

I have a source JSON object that I get from a server that looks like this:
{
"Property A": .098
}
I have a C# class that I deserialize the JSON into using the following:
public class foo {
[JsonProperty("Property A")]
public decimal PropertyA{ get; set;}
}
var ret = JsonConvert.DeserializeObject<foo>(File.ReadAllText(someJsonString);
This allows me to read in a JSON file and convert it to a C# object. But now I would like to write this object out to JSON but change the format to be this:
{
"property_a":.098
}
I currently have another class that is identical and the only difference is that I change the JsonProperty field to the new desired name:
public class foo {
[JsonProperty("property_a")]
public decimal PropertyA{ get; set; }
}
Is there a way using Newtonsoft to have a JsonProperty read as a particular value but write as a different?

Unity c# jsonUtility functions arent working

Want to convert a object to a json string and back.
My object:
[Serializable]
public class Save
{
public Levels PlayerLvl { get; set; }
public int Kills { get; set; }
}
function in code:
testfunction(Save savedata) {
//(int)savedata.PlayerLvl equals 1
//savedata.Kills equals 5
string json = JsonUtility.ToJson(savedata);
debug.log(json) // json equals "{}"
}
The same happens when I get a json string and want to convert it back:
testFunction(string jsonstring) {
//jsonstring is a valid json string that equals Save object
Save savedata = JsonUtility.FromJson<Save>(jsonstring);
// savedate equals a new Save object without content
}
whats wrong here?
Edit:
Json that I get:
{
"Kills": 5,
"PlayerLvl": 1
}
Levels enum:
public enum Levels {
Level1 = 1,
Level2 = 2
}
See from Manual: JSON Serialization
Supported types
The JSON Serializer API supports any MonoBehaviour subclass, ScriptableObject subclass, or plain class or struct with the [Serializable] attribute. When you pass in an object to the standard Unity serializer for processing, the same rules and limitations apply as they do in the Inspector: Unity serializes fields only; and types like Dictionary<> are not supported.
Unity does not support passing other types directly to the API, such as primitive types or arrays. If you need to convert those, wrap them in a class or struct of some sort.
So you want to remove all {get; set;} in order to use fields not properties
[Serializable]
public class Save
{
public Levels PlayerLvl;
public int Kills;
}

How to serialize dictionary with custom value type for MongoDb?

I have the following class, the instances of which I'd like to write to MongoDb:
public class ChartDefinitionBase
{
public ChartDefinitionBase(ObjectId id, IDictionary<ISite, IExample> examples)
{
ObjectId = id;
Examples = examples;
}
[BsonIgnoreIfDefault]
[BsonId(IdGenerator = typeof(ObjectIdGenerator))]
public ObjectId ObjectId { get; private set; }
[BsonDictionaryOptions(DictionaryRepresentation.ArrayOfDocuments)]
public IDictionary<ISite, IExample> Examples{ get; private set; }
}
When I attempt to call 'InsertOne()' on an instance of this type, I get the following ArgumentException:
GenericArguments[1], 'System.Collections.Generic.List{1}[System.Collections.Generic.KeyValuePair{2}[System.String,System.Object]]',
on 'MongoDB.Bson.Serialization.Serializers.ImpliedImplementationInterfaceSerializer{2}[TInterface,TImplementation]' violates the constraint of type 'TImplementation'.
If I convert the dictionary value type to a string, for instance, the exception disappears and serialization works great. However if I use a concrete implementation of IExample, I get the same exception.
How do I go about getting a dictionary with a custom value type to serialize?

Serialize to JSON Array of object<string, string>

I need my JSON output to be like the following (array of object}:
{
"values":[{"1","one"},{"2","two"},{"3","three"},{"4","four"}]
}
However, when I serialize the following C# class:
public class MyObject
{
public List<string>[] values {get;set}
}
It results in the following (array of array):
{
"values":[["1","one"],["2","two"],["3","three"],["4","four"]]
}
I've tried many variations on this object. Like the following:
public class MyObject
{
public KeyValuePair[] values {get;set}
}
Which gives me (array of KeyValuePair):
{
"values":[{"Key":"1","Value":"one"},{"Key":"2","Value":"two"},{"Key":"3","Value":"three"},{"Key":"4","Value":"four"}]
}
Is there a C# object property which would serialize to an array of json objects which do not have the object property names included?:
{
"values":[{"1","one"},{"2","two"},{"3","three"},{"4","four"}]
}
I may be answering my own question here, but here is what I found. The following will return an array of objects without property names. However, it is a hack and uses the Dictionary Key as the json property name:
public class MyObject
{
public Dictionary<string, string>[] values { get; set; }
}
Which yields the following:
{
"values":[{"1":"one"},{"2":"two"},{"3":"three"},{"4":"four"}]
}

How to create a list of dictionary objects of unknown value type?

I'm creating a CInformation class that will include various types of information. One type of the information it will expose are Parameters. Each parameter can be typed with any of the following types: int, short, string. Additionally, any parameter may have several possible values based on a string key. So I thought of creating a Dictionary<string, T> to hold all possible values for a parameter, but the problem arises when I try to declare my Parameters list. I created the following classes:
public class CParameter<T>
{
public object ParameterType { get; set; }
public Dictionary<string,T> ValueByString;
}
public class CInformation
{
public string Version { get; set; }
public string Name{ get; set; }
public List<CParameter<object>> Parameters; // cannot cast any of my types to object, obviously!
}
Any suggestions how I could get around my issue? I open to different solutions to my problem, not necessarily the same design I have above. Thank you.
EDIT: The main feature I want to achieve is to be able to have a list of dictionaries of different value types.
Using object to specialize a generic type is rather suspicious. If you do that, you might as well not even use a generic type at all. :-)
I think the issue here is that you want your instances of CParameter<T> to be specialized for different parameter types, and you want the parameters list on the CInformation class to contain different kinds of CParameter<T>.
In other words:
namespace Scratch
{
class Program
{
static void Main(string[] args)
{
CParameter<int> ints = new CParameter<int>();
CParameter<long> longs = new CParameter<long>();
CInformation info = new CInformation();
info.AddParameter(ints);
info.AddParameter(longs);
CParameter<int> ints2 = info.GetParameter<int>();
// ints2 and ints will both refer to the same CParameter instance.
}
}
public class CParameter<T>
{
public Type ParameterType { get { return typeof(T); } }
public Dictionary<string, T> ValueByString;
}
public class CInformation
{
public string Version { get; set; }
public string Name { get; set; }
private List<object> parameters;
public CInformation()
{
this.parameters = new List<object>();
}
public void AddParameter<T>(CParameter<T> parameter)
{
this.parameters.Add(parameter);
}
public CParameter<T> GetParameter<T>()
{
foreach (object parameter in this.parameters)
{
if (parameter is CParameter<T>)
return (CParameter<T>)parameter;
}
throw new Exception("Parameter type " + typeof(T).FullName + " not found.");
}
}
}
Note that the List<object> in that example could just as well be an ArrayList.
Also, I have a hunch that you're going to want to retrieve those CParameter objects by name rather than just by type. So consider adding a Name property to CParameter, and a name parameter to the GetParameter method. Then iterate over the list to find the property with the right name. Casting the result before returning it will verify that the type is the one you expected.
Or better yet, store the parameters in a Dictionary<string,object> instead of just a list, and use the parameter names as keys.

Categories

Resources