I have a method:
public object getData()
{
//make an external call
}
when executing getData(), we get an object that looks like this:
{
"Location":
{
"LocationID":1,
"ABCIsCopperFiberNidBit":0,
"ABCCopperJunctionID":0,
"ABCFiberJunctionID":0,
"ABCGrade":0,
"ABCCopperDSLAMDistance":0
}
}
from the above i need to convert this to a concrete datatype
such as a List of these:
public class LocationModel
{
public int locationId{get;set;}
public string key {get;set;}
public string value {get;set;}
}
the result I am looking for is a List<LocationModel>:
locationid=1,
key=ABCIsCopperFiberNidBit,
value=0
locationid=1
key = ABCCopperJunctionID,
value=0
etc
How do I convert from this object to the desired strongly-typed datatype?
My question is not for the purpose of you to do my work for me. I am a moderately-experienced developer, and I am having trouble digging through all the different ways of accomplishing this task.
Something like Json.NET would work well:
string json = #"{
""Location"":
{
""LocationID"":1,
""ABCIsCopperFiberNidBit"":0,
""ABCCopperJunctionID"":0,
""ABCFiberJunctionID"":0,
""ABCGrade"":0,
""ABCCopperDSLAMDistance"":0
}
}";
then:
var obj = (JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(json);
var loc = obj["Location"];
var locid = loc["LocationID"].Value<int>();
var list = new List<LocationModel>();
foreach(var prop in loc.Children().OfType<JProperty>())
{
if (prop.Name == "LocationID") continue;
list.Add(new LocationModel
{
locationId = locid,
key = prop.Name,
value = prop.Value.ToString()
});
}
Related
I use FastMember to get values out of objects and nested objects. If a property is a string or int everything works fine. But now I want to get the values also for collections. Here is my code so far:
// Set accessor
var sourceAccessor = ObjectAccessor.Create(source);
if (sourceAccessor.Target.GetType().GetInterface(nameof(ICollection)) != null || sourceAccessor.Target.GetType().GetInterface(nameof(IEnumerable)) != null)
{
foreach (/* idk */)
{
// READ & RETURN VALUES HERE
}
}
An object could look like this:
{
Id: 1,
Surname: Doe,
Prename: John,
Professions: [
{ Name: ab },
{ Name: xy }
]
}
Which means professions would result in a problem.
Any advise how I can solve this problem? Thanks!
It's not obvious from the question what the data type of the source variable is, but you should just be able to check if the value returned by the accessor implements IEnumerable or not and act accordingly.
Here's a quick worked example that iterates over the Professions property of a 'Person' object and just dumps the ToString() representation to the console - if you wanted to dive into each Profession object using FastMember you could construct another ObjectAccessor to do it, I guess - it's not clear what your goal is once you're iterating.
The same tactic will work if you're building the ObjectAccessor directly from an array - you just check if the accessor.Target is IEnumerable and cast-and-iterate in a similar fashion.
class Program
{
static void Main(string[] args)
{
var p = new Person
{
Professions = new List<Profession>
{
new Profession("Joker"),
new Profession("Smoker"),
new Profession("Midnight toker")
}
};
var accessor = ObjectAccessor.Create(p);
var professions = accessor[nameof(Person.Professions)];
if (professions is IEnumerable)
{
foreach (var profession in (IEnumerable)professions)
{
Console.WriteLine(profession);
}
}
}
}
class Person
{
public List<Profession> Professions { get; set; }
}
class Profession
{
public string Name { get; set; }
public Profession( string name)
{
Name = name;
}
public override string ToString()
{
return Name;
}
}
Consider the following mutable object:
class SomePoco
{
public int Id{get;set;}
public string Name{get;set;}
}
Let's round trip it through Json.NET:
var p=new SomePoco{Id=4,Name="spender"};
var json=JsonConvert.SerializeObject(p);
var pr = JsonConvert.DeserializeObject<SomePoco>(json);
Console.WriteLine($"Id:{pr.Id}, Name:{pr.Name}");
All is good.
Now, let's make out POCO immutable and feed values via a constructor:
class SomeImmutablePoco
{
public SomeImmutablePoco(int id, string name)
{
Id = id;
Name = name;
}
public int Id{get;}
public string Name{get;}
}
... and round-trip the data again:
var p = new SomeImmutablePoco(5, "spender's immutable friend");
var json = JsonConvert.SerializeObject(p);
var pr = JsonConvert.DeserializeObject<SomeImmutablePoco>(json);
Console.WriteLine($"Id:{pr.Id}, Name:{pr.Name}");
Still good.
Now, let's make a small change to our immutable class by renaming a constructor parameter:
class SomeImmutablePoco
{
public SomeImmutablePoco(int pocoId, string name)
{
Id = pocoId;
Name = name;
}
public int Id{get;}
public string Name{get;}
}
then:
var p = new SomeImmutablePoco(666, "diabolo");
var json = JsonConvert.SerializeObject(p);
var pr = JsonConvert.DeserializeObject<SomeImmutablePoco>(json);
Console.WriteLine($"Id:{pr.Id}, Name:{pr.Name}");
Oh dear... It looks like Json.NET is doing some reflective magic over the names of our constructor parameters and matching them to property names in our POCO/json. This means that our freshly deserialized object doesn't get an Id assigned to it. When we print out the Id, it's 0.
This is bad, and particularly troublesome to track down.
This problem might exist in a large collection of POCOs. How can I automate finding these problem POCO classes?
Here is the code that finds such classes using reflection:
var types = new List<Type>() { typeof(SomeImmutablePoco) }; // get all types using reflection
foreach (var type in types)
{
var props = type.GetProperties(bindingAttr: System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
foreach (var ctor in type.GetConstructors())
{
foreach (var param in ctor.GetParameters())
{
if (!props.Select(prop => prop.Name.ToLower()).Contains(param.Name.ToLower()))
{
Console.WriteLine($"The type {type.FullName} may have problems with Deserialization");
}
}
}
}
You can map your json property like that:
class SomeImmutablePoco
{
public SomeImmutablePoco(int pocoId, string name)
{
Id = pocoId;
Name = name;
}
[JsonProperty("pocoId")]
public int Id { get; }
public string Name { get; }
}
I have two variables that contain true/false data. THe first variable can be null but the second variable is always non null. Both variables will always be the same length.
var AnswerGridCorrect = "000111"; // or null
var AnswerGridResponses = "000011";
How could I change this data into an object oriented form. I already created classes and these are below. Here's is what I need the output to look like when converted to JSON:
"answers":[ // Json conversion made Answers into answers
{"correct":null,"response":true},
{"correct":null,"response":true},
{"correct":null,"response":true},
{"correct":null,"response":false}
}
Note that I am using LINQ to output the data so I think what I need is a function with parameters something like this:
.Select((t, index) => new {
Answer = t.Answer,
Answers = makeAnswer(t.AnswerGridCorrect,
t.AnswerGridResponses)
});
I am not sure if this helps but here were the classes I was using when I did this from JSON:
public class AnswerRow
{
public bool? Correct { get; set; }
public bool Response { get; set; }
}
public class AnswerRowList
{
public IList<AnswerRow> AnswerRows { get; set; }
}
Here is an implementation for your makeAnswers method:
public List<AnswerRow> makeAnswers(string c, string r)
{
var result = new List<AnswerRow>();
for(var i=0; i<r.Length; i++)
{
result.Add(
new AnswerRow {
Correct = c!=null?new Nullable<bool>(c[i]=='1'):null,
Response = r[i]=='1'
});
}
return result;
}
Rene's answer is probably correct, but here's the (unnecessarily complex) Linq way:
AnswerRowList MakeAnswer(string answerGridCorrect, string answerGridResponses)
{
return new AnswerRowList()
{
AnswerRows = answerGridResponses.Zip(
answerGridCorrect == null ?
Enumerable.Repeat<bool?>(null, answerGridResponses.Length) :
answerGridCorrect.Select(x => new Nullable<bool>(x == '1')),
(r, c) => new AnswerRow()
{
Correct = c,
Response = r == '1'
}).ToList()
};
}
I am having some trouble deserializing a Json string to use in an api wrapper I am currently writing. This is the json string in question:
{
"Search":[
{
"Title":"Clerks.",
"Year":"1994",
"imdbID":"tt0109445",
"Type":"movie"
},
{
"Title":"Clerks II",
"Year":"2006",
"imdbID":"tt0424345",
"Type":"movie"
}
]
}
This is the method I am currently using to process it.
public static Dictionary<string, string> FetchTitlesListDictionary(string searchQuery)
{
string searchResult = SendRequest(new[] { "?s=", searchQuery });
JObject parser = JObject.Parse(searchResult);
var movieDictionary = new Dictionary<string, string>();
for (int i = 0; i < parser["Search"].Count(); i++)
{
if (!movieDictionary.ContainsKey((string)parser["Search"][i]["imdbID"]))
{
movieDictionary.Add((string)parser["Search"][i]["imdbID"],
(string)parser["Search"][i]["Title"]);
}
}
return movieDictionary;
}
Even though the code above works, I feel it could, somehow, be made simpler.
How would I go about achieving this?
Thanks!
var obj = JsonConvert.DeserializeObject<RootObject>(searchResult);
public class Search
{
public string Title { get; set; }
public string Year { get; set; }
public string imdbID { get; set; }
public string Type { get; set; }
}
public class RootObject
{
public List<Search> Search { get; set; }
}
If you really want to convert the RootObject to a dictionary, you can use
var movieDictionary = obj.Search.ToDictionary(s => s.imdbID, s => s.Title);
PS: see this site
Well, if you're open to not using the default serializer, I would just open up the package manager console and type
Install-Package ServiceStack.Text
Then it becomes as easy as
var myDictionary = JsonObject.Parse(myJsonString)
.ArrayObjects("Search")
.ToDictionary(key => key.Get("imdbID"), value => value.Get("Title"));
There might be a similar and just as simple way to do it with the newtonsoft serializer, but honestly I never use it, so i'm not sure.
Also same thing as EZI's answer, it's also really easy if you have the objects he created, then you can just
var myObject = myJsonString.FromJson<RootObject>();
//if you want the dictionary it's the same thing, standard linq
var dictionary = myObject.Search.ToDictionary(x => x.imdbId, x => x.Title);
but if all you need is a dictionary, I would just use the above method, it's fast and easy.
What I have is this:
string json = #"{'number': 3, 'object' : { 't' : 3, 'whatever' : 'hi', 'str': 'test'}";
How do I read the fields until I'm at 'object', then serialize the whole 'object' into a .NET type and then continue parsing?
Define your types:
public class Object
{
public int t { get; set; }
public string whatever { get; set; }
public string str { get; set; }
}
public class RootObject
{
public int number { get; set; }
public Object object { get; set; }
}
Then just deserialize it:
string json = #"{'number': 3, 'object' : { 't' : 3, 'whatever' : 'hi', 'str': 'test'}";
var deserialized = JsonConvert.DeserializeObject<RootObject>(json);
//do what you want
UPDATE
You didn't say it's dynamic, for such parsing there is many solutions.
Check the following:
Using JSON.NET for dynamic JSON parsing
Using C# 4.0 and dynamic to parse JSON
Deserialize JSON into C# dynamic object?
Parse JSON block with dynamic variables
Turning JSON into a ExpandoObject
To handle a dynamic type: use dynamic, to handle dynamic data such as XML or JSON use ExpandoObject.
UPDATE 2
Using Anonymous types to deserialize JSON data
UPDATE 3
Will this work for you:
string json = "{\"number\": 3, \"object\" : { \"t\" : 3, \"whatever\" : \"hi\", \"str\": \"test\"}}";
var deserialized = SimpleJson.DeserializeObject<IDictionary<string, object>>(json);
var yourObject = deserialized["object"] as IDictionary<string, object>;
if (yourObject != null)
{
var tValue = yourObject.GetValue("t");
var whateverValue = yourObject.GetValue("whatever");
var strValue = yourObject.GetValue("str");
}
public static object GetValue(this IDictionary<string,object> yourObject, string propertyName)
{
return yourObject.FirstOrDefault(p => p.Key == propertyName).Value;
}
Final result:
Or change to the following
if (yourObject != null)
{
foreach (string key in yourObject.Keys)
{
var myValue = yourObject.GetValue(key);
}
}
UPDATE 4 - SERVICE STACK
string json = "{\"number\": 3, \"object\" : { \"t\" : 3, \"whatever\" : \"hi\", \"str\": \"test\"}}";
var deserialized = JsonObject.Parse(json);
var yourObject = deserialized.Get<IDictionary<string, object>>("object");
if (yourObject != null)
{
foreach (string key in yourObject.Keys)
{
var myValue = yourObject.GetValue(key);
}
}
Result:
Look at ServiceStack's Dynamic JSON Parsing:
var myPoco = JsonObject.Parse(json)
.GetUnescpaed("object")
.FromJson<TMyPoco>();
This works for deserializing, I will update once I got serializing.
foreach(KeyValuePair<String,String> entry in JsonObject.Parse(json))
{
}
Edit: Looks like this only works for json objects. I still don't know how to iterate over JsonArrayObjects