How to find a specific value in an IDictionary<string, object>? - c#

This IDictionary<string, object> contains user data I'm logging into mongodb. The issue is the TValue is a complex object. The TKey is simply the class name.
For example:
public class UserData
{
public string FirstName { get; set; }
public string LastName { get; set; }
public Admin NewAdmin { get; set; }
}
public class Admin
{
public string UserName { get; set; }
public string Password { get; set; }
}
Currently, I'm trying to iterate through the Dictionary and compare types but to no avail. Is there a better way of doing this or am I missing the mark?
var argList = new List<object>();
foreach(KeyValuePair<string, object> kvp in context.ActionArguments)
{
dynamic v = kvp.Value;
//..compare types...
}

Just use OfType<>(). You don't even need the key.
public static void Main()
{
var d = new Dictionary<string,object>
{
{ "string", "Foo" },
{ "int", 123 },
{ "MyComplexType", new MyComplexType { Text = "Bar" } }
};
var s = d.Values.OfType<string>().Single();
var i = d.Values.OfType<int>().Single();
var o = d.Values.OfType<MyComplexType>().Single();
Console.WriteLine(s);
Console.WriteLine(i);
Console.WriteLine(o.Text);
}
Output:
Foo
123
Bar
Link to Fiddle

Related

get data from json array string to an string variable

I get from another app an HTTP request with a JSON payload like this:
{
"reportName": "myfile",
"type_1": "pdf",
"paramm": [
{ "REF": "value1"},
{ "whatevervalue2": "whatevervalue2" }
]
}
I receive the data and try to process it. I created a class to get the data from the JSON:
public class ReportId
{
public string reportName { get; set; }
public string type_1 { get; set; }
public object[] paramm { get; set; }
}
And here is the method where I process all the data on the API controller:
[HttpPost]
public IActionResult generate([FromBody] ReportId jsonResult)
{
try
{
var reportName = jsonResult.reportName;
var type = jsonResult.type_1;
var recParam = jsonResult.paramm;
//....
List<ReportParameter> parameters = new List<ReportParameter>();
foreach (var t in recParam)
{
string[] paramName;
paramName = t.ToString().Split(":");
parameters.Add(new ReportParameter()
{
Name = paramName[0],
Labels = new List<string>() { paramName[1] },
Values = new List<string>() { paramName[1] }
});
}
reportWriter.SetParameters(parameters);
//....
}
catch
{
return null;
}
}
I got no problems with reportName and type_1 but on paramm it gets kinda wonky. I need to get the values of that array from the JSON. I do manage to get them, but with "all the format". For example, after the split on the first one I would get:
"{\r\n \"REF\""
" \"value1\"\r\n}"
Is there any more elegant way to get the values from that paramm array without having to replace the characters that are not part of the "real" string?
Thanks in advance.
[EDIT for clarification]
On the JSON I'll get multiple parameters:
"paramm": [
{ "parameter1": "value1" },
{ "parameter2": "value2" },
{ "parameter3": "value3" }
]
The parameter name could be any word and the value could be any as well. Those parameters are being sent to an RDL to filter some queries, so I need to get the name (parameter1, 2, 3...) and its value and add it as a parameter on the iteration of each.
Yes, there is an easier way.
In your ReportId class, change the paramm member to be a List<Dictionary<string, string>> instead of object[].
public class ReportId
{
...
public List<Dictionary<string, string>> paramm { get; set; }
}
Then, in your generate method you can just get the key and value from each dictionary instead of needing to do string manipulation:
List<ReportParameter> parameters = new List<ReportParameter>();
foreach (var dict in recParam)
{
var kvp = dict.First();
parameters.Add(new ReportParameter()
{
Name = kvp.Key,
Labels = new List<string>() { kvp.Value },
Values = new List<string>() { kvp.Value }
});
}
I guess, Your ReportId class should be like this. I hope this will work.
public partial class ReportId
{
[JsonProperty("reportName")]
public string ReportName { get; set; }
[JsonProperty("type_1")]
public string Type1 { get; set; }
[JsonProperty("paramm")]
public Paramm[] Paramm { get; set; }
}
public partial class Paramm
{
[JsonProperty("REF", NullValueHandling = NullValueHandling.Ignore)]
public string Ref { get; set; }
[JsonProperty("whatevervalue2", NullValueHandling = NullValueHandling.Ignore)]
public string Whatevervalue2 { get; set; }
}

Select from one dictionary with a second dictionary

I have 2 dictionaries List<Dictionary<string, object>> like this:
[{"Id":"2","FirstName":null,"MiddleName":null,"LastName":null,"Birthday":null,"Username":null,"Password":null,"LastLogin":null,"CreateDateTime":null,"UpdateDateTime":null,"Blocked":null,"HasOrders":null}]
and have a Dictionary like this Dictionary<string, string> for filter
var dict = new Dictionary<string, object>
{
{ "Username", "myUsername" },
{ "Password", "myPassword" }
};
My question is how I can filter out within the first List the records with help of the second list.
Please note that I need a where statement with 2 or 3 dynamic keys/values in the second list. There are a lot of records in these JSON structures.
It be great if somebody can point me to the right direction.
--UPDATE--
something like as I want to have, but than without the foreach:
foreach(Dictionary<string, object> v in Data)
{
v.Where(x =>
x.Key.Contains(nList.Where(n => n.Key == x.Key && n.Value = x.Value)));
}
I have no idea on how todo this in LINQ
I suggest you do this in couple of steps. First step, obviously would be to convert the List> structure to a List. Handling it as Collection of Dictionary is not a good approach.
public class UserPass
{
public string Username{get;set;}
public string Password{get;set;}
}
public class User
{
public int Id { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public DateTime? Birthday { get; set; }
public string Username { get; set; }
public string Password { get; set; }
public DateTime? LastLogin { get; set; }
public DateTime? CreateDateTime { get; set; }
public DateTime? UpdateDateTime { get; set; }
public bool? Blocked { get; set; }
public bool? HasOrders { get; set; }
}
For example,
var dictionary1 = new Dictionary<string,object>()
{
["Id"]="2",
["FirstName"]=null,
["MiddleName"]=null,
["LastName"]=null,
["Birthday"]=null,
["Username"]="anuviswan",
["Password"]="password",
["LastLogin"]=null,
["CreateDateTime"]=null,
["UpdateDateTime"]=null,
["Blocked"]=null,
["HasOrders"]=null
};
var dictionary2 = new Dictionary<string,object>()
{
["Id"]="3",
["FirstName"]=null,
["MiddleName"]=null,
["LastName"]=null,
["Birthday"]=null,
["Username"]="user1",
["Password"]=null,
["LastLogin"]=null,
["CreateDateTime"]=null,
["UpdateDateTime"]=null,
["Blocked"]=null,
["HasOrders"]=null
};
var dataList= new List<Dictionary<string,object>>
{
dictionary1,dictionary2
};
var dict1 = new Dictionary<string, object>
{
{ "Username", "myUsername" },
{ "Password", "myPassword" }
};
var dict2 = new Dictionary<string, object>
{
{ "Username", "anuviswan" },
{ "Password", "password" }
};
var filterList = new List<Dictionary<string,object>> {dict1, dict2};
var dataObjectList = dataList.Select(x=> new User
{
Id = Convert.ToInt32(x[nameof(User.Id)]),
Username = Convert.ToString(x[nameof(User.Username)]),
Password = Convert.ToString(x[nameof(User.Password)]),
});
var filterObjectList = filterList.Select(x=>
new UserPass
{
Username = Convert.ToString(x[nameof(UserPass.Username)]),
Password = Convert.ToString(x[nameof(UserPass.Password)]),
});
With the new Lists in place, you can query as
var result =dataObjectList.Join(filterObjectList,
d=>d.Username,
f=>f.Username,
(x,y)=> new
{
Data = x,
Filter=y
})
.Where(x=>x.Data.Username.Equals(x.Filter.Username)
&& x.Data.Password.Equals(x.Filter.Password))
.Select(x=>x.Data);;

How to Map Object / Class Property to Dictionary When Object Property And Dictionary Key Names Are Different?

I am calling Bloomberg Server API (for Stock Market Data) and getting Data back in a Dictionary<string, object> Where the Key to the dictionary is the Field Name on Bloomberg's side, and the object contains the data value from Bloomberg and can be string, decimal, DateTime, boolean etc.
After I get the Bloomberg Data, I need to populate my strong type entities / classes with the values returned. Depending on what Field Names I send in my request to bloomberg, the returned Dictionary could have different key values. The problem I am having is, the bloomberg field name and my .net entity's property names don't match, so I am not sure I can do this mapping using AutoMapper or a similar library.
I also tried using a Tuple<string,string,object> where the 1st tuple item is the bloomberg field name, the 2nd tuple item is my entity's property name and the 3rd tuple item is the data value returned from bloomberg. That is not working out either (so far), so I am wondering if there is a simple straight-forward way of maintaining this bloombergfield<-->EntityProperty mapping and populate the Entity's value using the Bloomberg Data Value for the respective field. A Generic (i.e. using C# Generics) solution would be even better!
I have pasted below sample console app code so you can paste it and try it out. The 2 dictionaries, 1 for stockdata and other for bonddata have fake data, but you get the idea. I have also added comments below to re-iterate what I am trying to accomplish.
Thanks!!
namespace MapBBFieldsToEntityProperties
{
using System;
using System.Collections.Generic;
class Program
{
public class StockDataResult
{
public string Name { get; set; }
public decimal LastPrice { get; set; }
public DateTime SettlementDate { get; set; }
public decimal EPS { get; set; }
}
public class BondDataResult
{
public string Name { get; set; }
public string Issuer { get; set; }
public decimal Duration { get; set; }
public DateTime YieldToMaturity { get; set; }
}
static void Main(string[] args)
{
// Data Coming from Bloomberg.
// Dictionary Key is the Bloomberg Data Field Name.
// Dictionary Object is the Value returns and can be any .Net primitive Type
// Sample Data returned for a Stock Query to Bloomberg
Dictionary<string, object> dctBloombergStockData
= new Dictionary<string, object>
{
{ "NAME", "IBM" },
{ "PX_LAST", 181.30f },
{ "SETTLE_DT", "11/25/2013" } // This is Datetime value
};
// Sample Data returned for a Bond Query to Bloomberg
Dictionary<string, object> dctBloombergBondData =
new Dictionary<string, object>
{
{ "NAME", "IBM" },
{ "ISSUE_ORG","IBM Corp" },
{ "DURATION", 4.430f },
{ "YLD_TO_M", 6.456f }
};
// This is my Stock Entity
StockDataResult stockData = new StockDataResult();
// This is my Bond Entity
BondDataResult bondData = new BondDataResult();
// PROBLEM STATEMENT:
//
// Need to somehow Map the Data returned from Bloomberg into the
// Corresponding Strong-typed Entity for that Data Type.
// i.e.
// map dctBloombergStockData to stockData Entity instance as follows
//
// dctBloombergStockData."NAME" Key <--------> stockData.Name Property so that
// dctBloombergStockData["NAME"] value of "IBM" can be assigned to stockData.Name
//
// dctBloombergStockData."PX_LAST" Key <--------> stockData.LastPrice Property so that
// dctBloombergStockData["PX_LAST"] value 181.30f can be assigned to stockData.LastPrice value.
// ....
// .. you get the idea.
// Similarly,
// map dctBloombergBondData Data to bondData Entity instance as follows
//
// dctBloombergBondData."NAME" Key <--------> bondData.Name Property so that
// dctBloombergBondData["NAME"] value of "IBM" can be assigned to bondData.Name property's value
//
// dctBloombergBondData."ISSUE_ORG" Key <--------> bondData.Issuer Property so that
// dctBloombergBondData["ISSUE_ORG"] value 181.30f can be assigned to bondData.Issuer property's value.
//
// dctBloombergBondData."YLD_TO_M" Key <--------> bondData.YieldToMaturity Property so that
// dctBloombergBondData["YLD_TO_M"] value 181.30f can be assigned to bondData.YieldToMaturity property's value.
}
}
}
I am sure quite a few improvements are possible, but this is one way of specifying a mapping and using that map.
class Program
{
public class Mapper<TEntity> where TEntity : class
{
private readonly Dictionary<string, Action<TEntity, object>> _propertyMappers = new Dictionary<string, Action<TEntity, object>>();
private Func<TEntity> _entityFactory;
public Mapper<TEntity> ConstructUsing(Func<TEntity> entityFactory)
{
_entityFactory = entityFactory;
return this;
}
public Mapper<TEntity> Map<TProperty>(Expression<Func<TEntity, TProperty>> memberExpression, string bloombergFieldName, Expression<Func<object, TProperty>> converter)
{
var converterInput = Expression.Parameter(typeof(object), "converterInput");
var invokeConverter = Expression.Invoke(converter, converterInput);
var assign = Expression.Assign(memberExpression.Body, invokeConverter);
var mapAction = Expression.Lambda<Action<TEntity, object>>(
assign, memberExpression.Parameters[0], converterInput).Compile();
_propertyMappers[bloombergFieldName] = mapAction;
return this;
}
public TEntity MapFrom(Dictionary<string, object> bloombergDict)
{
var instance = _entityFactory();
foreach (var entry in bloombergDict)
{
_propertyMappers[entry.Key](instance, entry.Value);
}
return instance;
}
}
public class StockDataResult
{
public string Name { get; set; }
public decimal LastPrice { get; set; }
public DateTime SettlementDate { get; set; }
public decimal EPS { get; set; }
}
public static void Main(params string[] args)
{
var mapper = new Mapper<StockDataResult>()
.ConstructUsing(() => new StockDataResult())
.Map(x => x.Name, "NAME", p => (string)p)
.Map(x => x.LastPrice, "PX_LAST", p => Convert.ToDecimal((float)p))
.Map(x => x.SettlementDate, "SETTLE_DT", p => DateTime.ParseExact((string)p, "MM/dd/yyyy", null));
var dctBloombergStockData = new Dictionary<string, object>
{
{ "NAME", "IBM" },
{ "PX_LAST", 181.30f },
{ "SETTLE_DT", "11/25/2013" } // This is Datetime value
};
var myStockResult = mapper.MapFrom(dctBloombergStockData);
Console.WriteLine(myStockResult.Name);
Console.WriteLine(myStockResult.LastPrice);
Console.WriteLine(myStockResult.SettlementDate);
}
}
As you have said your self you need a mapping table. You can create a static read only dictionary in you type that would map each key filed returned from Bloomberg to property in your strongly typed class.
Here is how I would do it.
PS: I used linqpad to test.
PPS: You can add as many mapper(s) to the dictionary as need be. You also need fast-member to run this code.
void Main()
{
var dctBloombergStockData = new Dictionary<string, object>
{
{ "NAME", "IBM" },
{ "PX_LAST", 181.30f },
{ "SETTLE_DT", "11/25/2013" } // This is Datetime value
};
StockDataResult.FromBloombergData(dctBloombergStockData);
}
// Define other methods and classes here
interface IMapper
{
string PropertyName { get; }
object Parse(object source);
}
class Mapper<T, TResult> : IMapper
{
private Func<T, TResult> _parser;
public Mapper(string propertyName, Func<T, TResult> parser)
{
PropertyName = propertyName;
_parser = parser;
}
public string PropertyName { get; private set; }
public TResult Parse(T source)
{
source.Dump();
return _parser(source);
}
object IMapper.Parse(object source)
{
source.Dump();
return Parse((T)source);
}
}
public class StockDataResult
{
private static TypeAccessor Accessor = TypeAccessor.Create(typeof(StockDataResult));
private static readonly Dictionary<string, IMapper> Mappers = new Dictionary<string, IMapper>(StringComparer.CurrentCultureIgnoreCase){
{ "NAME", new Mapper<string, string>("Name", a => a) },
{ "PX_LAST", new Mapper<float, decimal>("LastPrice", a => Convert.ToDecimal(a)) },
{ "SETTLE_DT", new Mapper<string, DateTime>("SettlementDate", a => DateTime.ParseExact(a, "MM/dd/yyyy", null)) }
};
protected StockDataResult()
{ }
public string Name { get; set; }
public float LastPrice { get; set; }
public DateTime SettlementDate { get; set; }
public decimal EPS { get; set; }
public static StockDataResult FromBloombergData(Dictionary<string, object> state)
{
var result = new StockDataResult();
IMapper mapper;
foreach (var entry in state)
{
if(!Mappers.TryGetValue(entry.Key, out mapper))
{ continue; }
Accessor[result, mapper.PropertyName.Dump()] = mapper.Parse(entry.Value);
}
return result;
}
}
How about:
stockData.Name = dctBloombergStockData["NAME"];
stockData.LastPrice = dctBloombergStockData["PX_LAST"]
//and so on...

c# JavaScriptSerializer on JSON containing string + dictionary

May i know how to parsing the JSON stated as below..... the JSON is part of Yahoo OAuth Contacts list.
JSON:
"fields":[{
"id":2,
"type":"nickname",
"value":"Hello"
},
{
"id":3,
"type":"email",
"value":"MyTesting#hotmail.com"
},
{
"id":1,
"type":"name",
"value":{
"givenName":"Otopass",
"middleName":"Test",
"familyName":"Hotmail"
},
}],
C# object :
private class fields
{
public string id { get; set; }
public string type { get; set; }
//public string value { get; set; } //Stuck At Here !!!!
//public Dictionary<string, string> value { get; set; } //Stuck At Here !!!!
}
How to parse the "value"?? since it's combination type of String & Dictionary.
I can't answer it using JavaScriptSerializer but you can do it using json.Net and Linq
var jObj = JObject.Parse(json);
var fields = jObj["fields"]
.Select(x => new Field
{
Id = (int)x["id"],
Type = (string)x["type"],
Value = x["value"] is JValue
? new Dictionary<string,string>(){{"",(string)x["value"]}}
: x["value"].Children()
.Cast<JProperty>()
.ToDictionary(p => p.Name, p => (string)p.Value)
})
.ToList();
private class Field
{
public int Id { get; set; }
public string Type { get; set; }
public Dictionary<string, string> Value { get; set; }
}
PS: I fixed your partial json string as
string json =
#"{""fields"":[
{
""id"":2,
""type"":""nickname"",
""value"":""Hello""
},
{
""id"":3,
""type"":""email"",
""value"":""MyTesting#hotmail.com""
},
{
""id"":1,
""type"":""name"",
""value"":{
""givenName"":""Otopass"",
""middleName"":""Test"",
""familyName"":""Hotmail""
}
}
]}";

Storing in a nested dictionary C#

Broadcom
Connection Name: Local Area Connection
DHCP Enabled: No
IP address(es)
[01]: abc.de.fg.h
I would like to put this into a Dictionary<string, Dictionary <string, string>>
So Broadcom would be the key in the first dictionary and the rest would be value the value. The value should be stored as a dictionary where Connection Name is the key and Local Area Connection is the value. How do I go about doing that? I am new to programming. Thanks for the help.
Please do yourself a great favour and use a class for that, because in two months time you will not understand your code:
public class WhatIsThis {
private List<IPAddress> ipAddresses = new List<IPAddress>();
public string Name { get; set; }
public string ConnectionName { get; set; }
public bool DHCPEnabled { get; set; }
public List<IPAddress> IPAddresses { get return ipAddresses; }
}
Now you can keep a List<WhatIsThis> around. If you have justa few of them, the O(n) cost of looking a value up is negligible. If you want a lookup by name in O(1) fashion, you can map to a Dictionary as such:
var dict = listOfWhatisThis.ToDictionary(k=>k.Name, v=>v}
Gives you a Dictionary of type Dictionary<string,WhatIsThis> . What do you think, will you understand this better in 2 weeks time, or rather your scary Dictionary?
http://msdn.microsoft.com/en-us/library/bb531208.aspx
var dic = new dictionary<string, dictionary <string, string>>(
{"Broadcom",
new dictionary <string, string>(
{
{"Connection Name", "Local Area Connection"},
{"DHCP Enabled", "No"},
{"IP address(es) [01]", "abc.de.fg.h"}
}
)
}
);
My only concern would be that the IP Addresses should themselves be in a dictionary within the settings for a connection, not a single string, and thus the sub-dictionary would need to be dictionary<string, object>.
Similar to flq's answer, here's a more comprehensive solution which makes both subdictionaries:
using System.Collections.Generic;
using System.Linq;
namespace LINQDictionaryDemo
{
public class IPAddress
{
public int Index { get; private set; }
public string Value { get; private set; }
public IPAddress(int Index, string Value)
{
this.Index = Index;
this.Value = Value;
}
}
public class NetworkConnection
{
public string Name { get; set; }
public string ConnectionName { get; set; }
public bool DHCPEnabled { get; set; }
public List<IPAddress> IPAddresses { get; set; }
public Dictionary<string, object> ToDictionary()
{
return new Dictionary<string, object>
{
{ "ConnectionName", ConnectionName }
, { "DHCPEnabled", DHCPEnabled.ToString() }
, {"IPAddresses", IPAddresses.ToDictionary(k => k.Index, v => v.Value)}
};
}
}
public static class Demo
{
public static void Run()
{
var lnc = new List<NetworkConnection>
{
new NetworkConnection
{
Name = "Broadcom",
ConnectionName = "Local Area Connection",
DHCPEnabled = false,
IPAddresses = new List<IPAddress> {new IPAddress(1, "abc.de.fg.h")}
}
};
var dic = lnc.ToDictionary(k => k.Name, v => v.ToDictionary());
}
}
}

Categories

Resources