Help needed to convert a javascript object to corresponding C# dictionary - c#

Hi I'm kind of newbie in C#, I have this javascript code that I need to convert into corresponding c# dictionary
given below is the javascript code
EXCHANGES = {
"ICE": {
source: "SPC",
name: "ICE Futures Europe",
assetTypes: {
CER: {
spot: "ECX CER DAILY FUTURE",
fut: "ECX CER FUTURE"
},
EUA: {
spot: "ECX EUA DAILY FUTURE",
fut: "ECX EUA FUTURE"
}
}
},
"CLIMEX": {
source: "CLX",
name: "Climex Spot Market",
symbols: {
CER: {
spot: ["CER"]
},
EUA: {
spot: ["EUA 08-12"]
}
}
},
"BLUENEXT": {
source: "BLNXT",
name: "Bluenext",
symbols: {
CER: {
spot: ["1000019-82-1"]
},
EUA: {
spot: ["1000019-81-1"]
}
}
}
};
So far what I have manage is this
public Dictionary<string, Dictionary<string, string>> Exchanges = new Dictionary<string, Dictionary<string, string>> {
{"ICE ECX", new Dictionary<string, string> {
{"source", "SPC"},
{"name", "ICE Futures Europe"},
{"exchange", "ICE" }
}},
{"Climex", new Dictionary<string, string> {
{"source", "CLX"},
{"name", "Climex Spot Market"},
{"exchange", "Climex" }
}},
{"BlueNext", new Dictionary<string, string> {
{"source", "BLNXT"},
{"name", "Bluenext"},
{"exchange", "BlueNext" }
}},
{"Green Exchange", new Dictionary<string, string> {
{"source", "SPC"},
{"name", "NYMEX: Futures"},
{"exchange", "NYMEX" }
}},
{"NYMEX_FA", new Dictionary<string, string> {
{"source", "SPC"},
{"name", "NYMEX: Futures Acess"},
{"exchange", "NYMEX_FA" }
}}
};
Can anyone of you can guide me to the correct way to do this any help will be appreciated.
thanks
Pranay

I'd use a JSON Parser. Like this.
In that way you can retrieve the properties and values after parsing from the JObject.
string jsonText = #"{
prop1: 1,
prop2: 'Some String',
'prop3': {
iProp1: 1,
iProp2: 2
}";
JObject parsedJson = JObject.Parse(jsonText);

I'd give a try to ExpandoObject, which is dynamic and implements IDictionary<string,object>. For instance, you can write the following code:
dynamic x = new ElasticObject();
x.Ice = new ExpandoObject();
x.Ice.Source = "SPC";
x.Ice.Name = "Ice Futures Europe";
x.AssetTypes = new ExpandoObject();
x.AssetTypes.CER = new ExpandoObject();
x.AssetTypes.CER.Spot = "EXC CER DAILY FUTURE";
x.AssetTypes.CER.Fut = "EXC CER FUTURE";
x.EUA = new ExpandoObject();
x.EUA.Spot = "ECX EUA DAILY FUTURE";
x.EUA.Fut = "ECX EUA FUTURE";
On MSDN you can read more about ExpandoObject here.
If you need a yet smarter object, there is the ElasticObject (described here). Using it you can skip the declaration of the nested Expandos, like this:
dynamic x = new ExpandoObject();
x.Ice.Source = "SPC";
x.Ice.Name = "Ice Futures Europe";
x.AssetTypes.CER.Spot = "EXC CER DAILY FUTURE";
x.AssetTypes.CER.Fut = "EXC CER FUTURE";
x.EUA.Spot = "ECX EUA DAILY FUTURE";
x.EUA.Fut = "ECX EUA FUTURE";
Hope this helps.

This what I did basically I created classes since maintaining this level of dictionary would have been cumbersome
public class Exchange
{
public string Source {get; set;}
public string Name {get; set;}
public Dictionary<string, AssetTypeSymbol> AssetTypes {get; set;}
public Dictionary <string,AssetTypeSymbol>Symbols {get; set;}
}
public class AssetTypeSymbol
{
public IList<string> Spot {get; set;}
public IList<string> Fut {get; set;}
}
public Dictionary<string,Exchange> Exchanges = new Dictionary<string,Exchange>
{
{"ICE ECX", new Exchange() {
Source = "SPC",
Name = "ICE Futures Europe",
AssetTypes = new Dictionary<string, AssetTypeSymbol>() {
{"CER", new AssetTypeSymbol() {
Spot = new string[] { "ECX CER DAILY FUTURE" },
Fut = new string[] { "ECX CER FUTURE" }
}},
.......... and so on

Related

Append to list in DynamoDB(C#)

I have a Dynamo table of US states and each state has a list of businesses. The structure is as follows:
{"Name": {S: "Ohio"},"Businesses":{"L": [ { M: {"Name":{"S":"McDonalds"}}, { M: {"Name":{"S":"IHOP"}} ] }
My goal is to write a function that can take a list of businesses and IF they don't exist already append them to the list of businesses, I have gotten this far:
public async Task UpdateStatesBusinessList(Buisness buisness)
{
var dynamoRequest = new UpdateItemRequest
{
Key = new Dictionary<string, AttributeValue>
{
{"Name", new AttributeValue{S = buisness.Name}}
},
ExpressionAttributeNames = new Dictionary<string, string>
{
{"#B", "Businesses" }
},
ExpressionAttributeValues = new Dictionary<string, AttributeValue>
{
{":B", new AttributeValue{L = business.Businesses}};
}
}
}
Public class Business
{
public string Name {get; set;}
}
We can pretend I have a hard coded list of businesses like:
BusinessList = new List<Business>
{
new Buisness {Name = "Chilis"}, new Buisness {Name = "BurgerKing"},etc...
}
I know I need to use an update expression with SET and use the if_not_exists() with list_append(). I need help constructing the request because my ExpressionAttributeValue is not correct... Any advise would be great, I have looked through all the AWS documentation and countless websites and have not been able to get it to work.

Dictionary with tuples values returning null?

I have a class with a dictionary defined as a private member :
Dictionary<int, (string, string)> arenaIdToSetAndNumber = new Dictionary<int, (string, string)>()
{
{ 70506, ("c16", "337") },
{ 70507, ("c16", "340") },
{ 70508, ("c16", "343") },
{ 70509, ("c16", "346") },
{ 70510, ("c16", "349") },
};
While debugging, I get to an item corresponding to key 70506, I see this with 2 watches:
I try doing var test = arenaIdToSetAndNumber[c.grpId].Item1 and test is set to null just as seen in the second watch! I don't understand why
The debugger and the watcher are not able to infer what is Item1 from the indexer operator [], thus will give you null in the watch. But once you run the code, it will just work fine for reading purpose. For writing purpose instead, you need to take out the whole tuple, edit it and reinsert in the dictionary:
static void Main(string[] args)
{
Dictionary<int, (string, string)> arenaIdToSetAndNumber = new Dictionary<int, (string, string)>()
{
{ 70506, ("c16", "337") },
{ 70507, ("c16", "340") },
{ 70508, ("c16", "343") },
{ 70509, ("c16", "346") },
{ 70510, ("c16", "349") },
};
var myTuple = arenaIdToSetAndNumber[70509];
myTuple.Item1 = "c18";
arenaIdToSetAndNumber[70509] = myTuple;
//System.Console.WriteLine(arenaIdToSetAndNumber[70509].Item1); // This prints c18
}
Otherwise, in one line, just recreate the whole tuple:
arenaIdToSetAndNumber[70509] = ("c18", arenaIdToSetAndNumber[70509].Item2);
All of this because the ValueTuple is a struct. Similar question here
This does not use tuples but solves your problem. Since you want to read the values create an immutable class, use properties to retrive the values.
public class Contents
{
private readonly string leftValue;
private readonly string rightValue;
public Contents(string aLeftValue, string aRightValue)
{
leftValue = aLeftValue;
rightValue = aRightValue;
}
public string LeftValue => leftValue;
public string RightValue => rightValue;
}
Modify your code to use the new class.
Dictionary<int, Contents> arenaIdToSetAndNumber = new Dictionary<int, Contents>()
{
{ 70506, new Contents("c16", "337") },
{ 70507, new Contents("c16", "340") },
{ 70508, new Contents("c16", "343") },
{ 70509, new Contents("c16", "346") },
{ 70510, new Contents("c16", "349") },
};
And you can test it with this.
var content = arenaIdToSetAndNumber[70506];
string leftValue = content.LeftValue;
string rightValue = content.RightValue;
Hope this solves your problem.

Convert dot notation to JSON

How do i convert dot notation to json
The dot notation can have any depth
All data is current like this:
Dictionary<string, string> data = new Dictionary<string, string>
{
{"Company.Website", "Hjemmeside"},
{"Company.TextHeaderPlaceholder", "Firmanavn"},
{"Company.User.Manager.Repositories.CreateAsync.ArgumentNullException.InvalidCompanyId", "firma id fejl"},
{"BookingSettings.HelpText", "Hjælpe tekst på webshop"},
{"BookingSettings.OnGoingOrderValidation.Text", "Bestillings validering i gang"},
{"BookingSettings.OnGoingOrderValidation.Created", "Oprettet"},
{"BookingSettings.Url", "Kundelink til booking"}
};
Json result should be:
{
"Company": {
"Website": "Hjemmeside",
"TextHeaderPlaceholder": "Firmanavn",
"Users": {
"Managers": {
"Repositories": {
"CreateAsync": {
"ArgumentNullException": {
"InvalidCompanyId": "Can not create company user with out a company!"
}
}
}
}
}
},
"BookingSettings": {
"HelpText": "Hjælpe tekst på webshop",
"OnGoingOrderValidation": {
"Text": "Bestillings validering i gang",
"Created": "Oprettet"
},
"URL": "Kundelink til booking"
}
}
How do this the easy way?
I'd start by deserializing it to nested dictionaries.
public static Dictionary<string, object> DotNotationToDictionary(Dictionary<string, string> dotNotation)
{
Dictionary<string, object> root = new Dictionary<string, object>();
foreach (var dotObject in dotNotation)
{
var hierarcy = dotObject.Key.Split('.');
Dictionary<string, object> current = root;
for (int i = 0; i < hierarcy.Length; i++)
{
var key = hierarcy[i];
if (i == hierarcy.Length - 1) // Last key
{
current.Add(key, dotObject.Value);
}
else
{
if (!current.ContainsKey(key))
current.Add(key, new Dictionary<string, object>());
current = (Dictionary<string, object>) current[key];
}
}
}
return root;
}
Once that's done you can use JsonSerializer.Serialize to convert the dictionaries to JSON (JavaScriptEncoder.UnsafeRelaxedJsonEscaping needed for "æ"):
Dictionary<string, string> dotNotation = new Dictionary<string, string>
{
{"Company.Website", "Hjemmeside"},
{"Company.TextHeaderPlaceholder", "Firmanavn"},
{"Company.User.Manager.Repositories.CreateAsync.ArgumentNullException.InvalidCompanyId", "firma id fejl"},
{"BookingSettings.HelpText", "Hjælpe tekst på webshop"},
{"BookingSettings.OnGoingOrderValidation.Text", "Bestillings validering i gang"},
{"BookingSettings.OnGoingOrderValidation.Created", "Oprettet"},
{"BookingSettings.Url", "Kundelink til booking"}
};
var betterDictionary = DotNotationToDictionary(dotNotation);
var json = JsonSerializer.Serialize(betterDictionary, new JsonSerializerOptions { WriteIndented = true, Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping });
Console.WriteLine(json);
Here's a fiddle with it.
This is the output:
{
"Company": {
"Website": "Hjemmeside",
"TextHeaderPlaceholder": "Firmanavn",
"User": {
"Manager": {
"Repositories": {
"CreateAsync": {
"ArgumentNullException": {
"InvalidCompanyId": "firma id fejl"
}
}
}
}
}
},
"BookingSettings": {
"HelpText": "Hjælpe tekst på webshop",
"OnGoingOrderValidation": {
"Text": "Bestillings validering i gang",
"Created": "Oprettet"
},
"Url": "Kundelink til booking"
}
}

RavenDB Index: Need a solution to merge 2 dictionary fields into a single dictionary, flatten it and make it searchable

We are building a nested UI view for a customer and require a solution to merge 2 dictionary fields into a single consolidated dictionary as well as make the keys searchable as though they are field names. I managed to create a Map/Reduce index using the techniques mentioned in http://ravendb.net/docs/2.5/client-api/advanced/dynamic-fields and https://groups.google.com/forum/#!msg/ravendb/c0HdJT-yyvQ/qvkVRrZfvmgJ.
public class ViewFolderResultWithIndividualProperties
{
public string EntryId { get; set; }
public List<KeyValuePair<string, string>> MetadataProperties { get; set; }
public List<KeyValuePair<string, string>> NamedProperties { get; set; }
public List<KeyValuePair<string, string>> Properties { get; set; }
public string FlattenedProperties { get; set; }
public string _ { get; set; }
}
MetadateProperties – it is a dictionary of Key, Value pairs. For e.g.,
"MetadataProperties": [
{
"Key": "JobName",
"Value": "one job"
},
{
"Key": "Organization",
"Value": "foo"
}]
NamesProperties – it is a dictionary of known Key, Value pairs. For e.g.,
"NamedProperties": [
{
"Key": "Tags",
"Value": ""
},
{
"Key": "Name",
"Value": "file-184"
},
{
"Key": "Uploader",
"Value": "rmani#transper.com"
},
{
"Key": "FileType",
"Value": "Jpg"
},
{
"Key": "Language",
"Value": "English"
}]
Properties – It is a merged Dictionary that contains the Key, Value pairs from both MetadataProperties and NamedProperties.
FlattenedProperties and _ are the properties that contains the flattened field values of “NamedProperties” and “MetadataProperties” respectively. I can’t figure out a way to flatten a computed Property like “Properties” (which combines both MetadataProperties and NamedProperties dictionaries). I tried Concat
Here’s the Index creation code:
public class PortalEntryViews_DocumentIdSplitIndex : AbstractIndexCreationTask<PortalEntry, ViewFolderResultWithIndividualProperties>
{
public PortalEntryViews_DocumentIdSplitIndex()
{
Map = portalEntries => from portalEntry in portalEntries
select new
{
EntryId = portalEntry.Id,
MetadataProperties = portalEntry.MetaData.Select(t => new KeyValuePair<string, string>(t.Key, t.Value)).ToList(),
NamedProperties = new List<KeyValuePair<string, string>> {
new KeyValuePair<string, string>("Tags", string.Join(",", portalEntry.Tags.Where(t => !t.IsInternal).Select(t=>t.Name))),
new KeyValuePair<string, string>("Name", portalEntry.Name),
new KeyValuePair<string, string>("Uploader", portalEntry.Uploader),
new KeyValuePair<string, string>("FileType", portalEntry.FileType),
new KeyValuePair<string, string>("Language", portalEntry.Language),
new KeyValuePair<string, string>("Name", portalEntry.Name) },
Properties = new List<KeyValuePair<string, string>>(),
FlattenedProperties = "",
_ = ""
};
Reduce = results => from result in results
group result by new { result.EntryId, result.MetadataProperties, result.NamedProperties, result.FlattenedProperties, result._ } into g
select new
{
EntryId = g.Key.EntryId,
MetadataProperties = g.Key.MetadataProperties,
NamedProperties = g.Key.NamedProperties,
Properties = g.Key.MetadataProperties.Concat(g.Key.NamedProperties).ToList(),
FlattenedProperties = g.Key.NamedProperties.Select(f => CreateField(f.Key, f.Value)),
_ = g.Key.MetadataProperties.Select(t => CreateField(t.Key, t.Value, true, true))
};
}
}
When I run a query like “Language:English” from RavenDb Explorer directly, it works and returns a projection. Whereas when I run the same query using LuceneQuery from within my C# code:
var entries =
session.Advanced.LuceneQuery<ViewFolderResultWithIndividualProperties>(
"PortalEntryViews/DocumentIdSplitIndex")
.WhereEquals("Language", "English").ToList();
I get this error:
Raven.Imports.Newtonsoft.Json.JsonSerializationException : Could not read value for property: FlattenedProperties ----> Raven.Imports.Newtonsoft.Json.JsonReaderException : Error reading string. Unexpected token: StartArray
My ultimate goal is to flatten the combined dictionary i.e. Properties field into a single field using CreateField() that can be searched using the keys as though they are field names. But, if I use a call like this:
Properties = g.Key.MetadataProperties.Concat(g.Key.NamedProperties).ToList().Select(t => CreateField(t.Key, t.Value, true, true)), it seems to run but when you look at the index from Ravendb Explorer, it shows the actual error:
Stage: Indexing Section:Reduce Description: ‘System.Collections.Generic.List’ does not contain definition for ‘Select’
Right now, I’m only able to flatten only one Dictionary (MetadataProperties) into that “_” field in reduce section, which works from both Ravendb Explorer and from C# code using LuceneQuery but that does not meet my requirement.
Can someone help me resolve this issue?
If you want to search key-value only, you can do it very simple
//the index
public class FlattenIndex: AbstractIndexCreationTask<PortalEntry>
{
public class ReduceResult
{
public string Key { get; set; }
public string Value { get; set; }
}
public FlattenIndex()
{
Map = portalEntries => from portalEntry in portalEntries
from p in portalEntry.MetadataProperties.Concat(portalEntry.NamedProperties)
select new
{
Key=p.Key,
Value=p.Value
};
}
}
//the query
using (var session = _docStore.OpenSession())
{
var someEntries = session.Query<FlattenIndex.ReduceResult, FlattenIndex>()
.Where(x => x.Key == "Language" && x.Value == "English")
.As<PortalEntry>()
.ToArray();
if (someEntries!=null)
foreach(var entry in someEntries )
{
Console.WriteLine(entry.Id);
}
}

Proper way to initialize a C# dictionary with values

I am creating a dictionary in a C# file with the following code:
private readonly Dictionary<string, XlFileFormat> FILE_TYPE_DICT
= new Dictionary<string, XlFileFormat>
{
{"csv", XlFileFormat.xlCSV},
{"html", XlFileFormat.xlHtml}
};
There is a red line under new with the error:
Feature 'collection initilializer' cannot be used because it is not part of the ISO-2 C# language specification
What is going on here?
I am using .NET version 2.
I can't reproduce this issue in a simple .NET 4.0 console application:
static class Program
{
static void Main(string[] args)
{
var myDict = new Dictionary<string, string>
{
{ "key1", "value1" },
{ "key2", "value2" }
};
Console.ReadKey();
}
}
Can you try to reproduce it in a simple Console application and go from there? It seems likely that you're targeting .NET 2.0 (which doesn't support it) or client profile framework, rather than a version of .NET that supports initialization syntax.
With C# 6.0, you can create a dictionary in the following way:
var dict = new Dictionary<string, int>
{
["one"] = 1,
["two"] = 2,
["three"] = 3
};
It even works with custom types.
You can initialize a Dictionary (and other collections) inline. Each member is contained with braces:
Dictionary<int, StudentName> students = new Dictionary<int, StudentName>
{
{ 111, new StudentName { FirstName = "Sachin", LastName = "Karnik", ID = 211 } },
{ 112, new StudentName { FirstName = "Dina", LastName = "Salimzianova", ID = 317 } },
{ 113, new StudentName { FirstName = "Andy", LastName = "Ruth", ID = 198 } }
};
See How to initialize a dictionary with a collection initializer (C# Programming Guide) for details.
Suppose we have a dictionary like this:
Dictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(1, "Mohan");
dict.Add(2, "Kishor");
dict.Add(3, "Pankaj");
dict.Add(4, "Jeetu");
We can initialize it as follows.
Dictionary<int, string> dict = new Dictionary<int, string>
{
{ 1, "Mohan" },
{ 2, "Kishor" },
{ 3, "Pankaj" },
{ 4, "Jeetu" }
};
Object initializers were introduced in C# 3.0. Check which framework version you are targeting.
Overview of C# 3.0
Note that C# 9 allows Target-typed new expressions so if your variable or a class member is not abstract class or interface type duplication can be avoided:
private readonly Dictionary<string, XlFileFormat> FILE_TYPE_DICT = new ()
{
{ "csv", XlFileFormat.xlCSV },
{ "html", XlFileFormat.xlHtml }
};
With С# 6.0
var myDict = new Dictionary<string, string>
{
["Key1"] = "Value1",
["Key2"] = "Value2"
};
Here is an example of Dictionary with Dictionary value
Dictionary<string, Dictionary<int, string>> result = new() {
["success"] = new() {{1, "ok"} , { 2, "ok" } },
["fail"] = new() {{ 3, "some error" }, { 4, "some error 2" } },
};
which is equivalent to this in JSON :
{
"success": {
"1": "ok",
"2": "ok"
},
"fail": {
"3": "some error",
"4": "some error 4"
}
}
The code looks fine. Just try to change the .NET framework to v2.0 or later.

Categories

Resources