Serialize to JSON Array of object<string, string> - c#

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"}]
}

Related

Skip empty arrays in JSON deserialize

I'm trying to read a JSON document from a REST web service with Newsoft.JsonNET
The document contains some empty arrays:
{
"values": [null]
}
This is how a filled array looks like:
{
"values": ["first", "second", "third"]
}
My model class looks like this:
[DataContract]
public class MyModel
{
[DataMember]
public IEnumerable<MyEnum> Values{ get; }
public MyModel(IEnumerable<MyEnum> values)
{
this.Values = values;
}
}
public MyEnum
{
First,
Second,
Third
}
The null in those empty array causes an ArgumentNullException.
How can I solve this?

Creating a custom JSON tokenizer

I am trying to parse JSON into a token object. Right now Im using JSON.Net to generate a static class, and parsing it using Json2csharp, but I would like to make each array element its own Token object and I'm not quite sure how to do that. Do I need to implement my own JSON parser? I can modify the JSON object as needed.
My JSON Deserializer: JSONopMap jo = JsonConvert.DeserializeObject<JSONopMap>(myjson2);
public class JSONopMap
{
List<List<string>>addr {get;set;}
}
JSON
{
'addr':[['~address'],['removeall','.'],['append',' ','~age']]
}
My end goal is to create a MyToken class like this:
public class MyToken
{
public enum tokenType {get;set;}
public List<string> parts {get;set;}
}
public class TokenParent{
public string ResultName{get;set;}
public List<MyToken> mytokens{get;set;}
}
public enum tokenType{Map,Append,Removeall,Lower}
So I would have three MyToken objects like this:
new MyToken{
tokenType=Map,
parts=new List<string>(){"~address"}
}
new MyToken{
tokenType=Removeall,
parts=new List<string>(){"."}
}
new MyToken{
tokenType=Append,
parts=new List<string>(){" ","~age"}
}
and a parent which contained them all:
new TokenParent{
ResultName="addr",
mytokens = (the tokens created above)
}

How to prevent _t and _v when inserting into MongoDB?

I'm utilizing Dictionary. After .insert() there are "_t" and "_v". Two posts here talked about serialization converting to JSON first then BSON. I'm using MongoDB's driver v2.4.3,
mCollection.InsertOne(x);
IMongoCollection<myDoc> mCollection = Db.GetCollection<myDoc>("whatever");
If I do JSON-to-BSON, it complains about can't convert BsonDocument to myDoc. Switching to IMongoCollection<BsonDocument> mCollection = Db.GetCollection<BsonDocument>("whatever"); still get _t and _v.
How to avoid _t and _v?
Here is my code of data type and utilization:
public class myObjForDictionary
{
//...
}
public class myDoc
{
// ... some other elements, then Dictionary
public Dictionary<string, object> myDictionary { get; set; }
}
// to instantiate the
class myClass
{
// define MongoDB connection, etc.
// instantiate myDoc and populate data
var x = new myDoc
{
//...
myDictionary = new Dictionary<string, object>
{
{ "type", "something" },
{ "Vendor", new object[0] },
{ "obj1", //data for myObjForDictionary
}
};
}
}
I think you're looking for the DictionarySerializationOption... which gives you a couple of different options out of the box to determine how your dictionary gets serialized.
You'll need to save some information (_t) of what object the deserializer needs to create when deserializing the object, if not it won't know what to create from the BSON.
Alternatively, you could change the Dictionary<string, object> to Dictionary<string, BsonDocument> and deal with the BsonDocuments directly within your code. This will be very similar to how you use JObject within Newtonsoft.Json.
It also happens when the passed model to mongo is not exactly the type that is defined on the model.
In this case, mongo will add _t as it identifies that you expect to read the inheritor's class type, and not the type that is defined on the model.
For example:
public class ParentClass { }
public class ChildClass : ParentClass { }
public class ModelToInsert
{
public ParentClass property { get; set; }
}
...
// ChildClass is passed instead of ParentClass
collection.InsertOne(new ModelToInsert { property = new ChildClass() });

Converting JSON to list of dictionaries

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.

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