I am reading a JSON file and stores the values as a object
Car : Name, Cost, Yearmodel
Now I need to pass these 3 JSON object values to this Testcasedata.
Likewise I need to pass multiple values while reading the JSON file data.
Any idea explaining on how to do this?
public string JSONParser()
{
StreamReader r = new StreamReader("ESAggregationQuery.json");
string jsonString = r.ReadToEnd();
m = JsonConvert.DeserializeObject<AggModel>(jsonString);
carName = m.carName;
costPrice = m.costPrice;
modelYear = m.modelYear;
return "1";
}
private static IEnumerable<TestCaseData> ESAggregativeTestData
{
get
{
yield return new TestCaseData[] { m.carName, m.costPrice, m.modelYear };
}
}
```
You don't "pass" data to your TestCaseData item. The data has to originate there. Try making the following changes...
Call your JSONParser from the getter of ESAggregativeTestData or add the code in there.
Change your yield statement to return a new TestCaseData, not an array. That's not an NUnit thing... it's just how IEnumerable works. If your JSON file, now or in the future, contains multiple test items, you will need to put all this in a loop.
You have not shown us your test code, which uses the data source. To work with the source you have given, it should take three arguments of the appropriate type.
Suggestion... next time provide more complete source code that shows what you are trying to do.
Related
I'm trying to work with JSON files to store a Class and I'm stuck with the deserialization.
I'm using the following NameSpace:
using System.Text.Json.Serialization;
I have a very simple class, made of 2 properties:
public EnumOfType Type { get; set; }
public double Price { get; set; }
I have 4 instances of this classe that I store in a list. When quiting the application, this list is saved in a JSON file.
string jsonString;
jsonString = JsonSerializer.Serialize(myListOfInstances);
File.WriteAllText(FileName, jsonString);
When I'm opening the Application, I want the JSON file to be loaded to recreate the instances.
I'm using the following method, which apparently works well.
string jsonString = File.ReadAllText(FileName);
myListOfInstances = JsonSerializer.Deserialize<List<MyClass>>(jsonString);
So far so good. When I check the content of the list, it is correctly populated and my 4 instances are there.
But then... how to use them?
Before the JSON, I was creating each instance (for example:)
MyClass FirstInstance = New MyClass();
FirstInstance.Type = EnumOfType.Type1;
FirstInstance.Price = 100.46;
Then I could manipulate it easily, simply calling FirstInstance.
myWindow.Label1.Content = FirstInstance.Price.ToString("C");
FirstInstance.Method1...
Now that the instances are in my list, I don't know how to manipulate them individually because I don't know how to call them.
It's probably obvious to most, but I'm still in the learning process.
Thank you for your help,
Fab
Based on how you have loaded the JSON file into your program, it looks like your variable myListOfInstances already contains all four MyClass objects ready to go. At this point you can use List accessors (or Linq if you want to be fancy) and do things such as the following:
myListOfInstances[0] //Gives you the first item in the list accessed by index
myListOfInstances.First() //Gives you the first item in the list (using linq)
foreach(var item in myListOfInstances) {
// this will iterate through all four items in the list storing each instance in
//the 'item' variable
}
etc...
EDIT: From my comment below. If you need to access values in a a list directly, you can search for specific conditions in the list using linq with the 'Where' method. The syntax is something like this:
myListOfInstances.Where(x => x.Property == SomePropertyToMatch)
Product_Details result = response.ResultAs<Product_Details>();
ArrayList myarr = result;
foreach (var item in result.ToString())
{
}
I want to change the variable result into an array list because this variable is containing data of full table and I need to iterate it.
IF i understand correctly, you are saying that the response contains multiple objects of type Product_Details. I do however need some more information; is the response coming in a JSON format (does it need to be serialized for example?).
Either way try something along the lines of this;
List<Product_Details> result = new List<Product_Details>(); // make a new list
result = response.ResultAs<List<Product_Details>>(); // assign response to list
foreach (Product_Details pd in result)
{
// use pd. to access the variable
}
// (i kept the .ResultAs since i dont know how or what your response object is/has,but did cast it to a list explicitly)
If you need to find out on how to deserialize JSON objects you can start Here
As discussed in the comments you said it was in JSON format, If you are using NewtonSoft.JSON (nuget) the code would be:
using (client)
{
HttpResponseMessage result = await client.GetAsync(tmpUri);
if (result.IsSuccessStatusCode)
{
var content = await result.Content.ReadAsStringAsync();
oc = JsonConvert.DeserializeObject<ObservableCollection<T>>(content);
}
}
(for the sake of clarity where this code should be i included the api call. you can of course, omit this.)
Let's say that in my WebAPI I'm receiving a json like this:
{
prop1: "sometext",
prop2: 123,
prop3: true,
prop4: [1,2,3,4,5],
prop5: ["text1", "text2", "text3"]
}
To work with this data, I transform it into this: dynamic data = System.Web.Helpers.Json.Decode(json);. In most cases it's really easy to work with it, but I'm struggling with a situation where I need to repass this data to a database. Most conversions are pretty straightforward, making it easy to iterate over the DynamicJsonObject and send the information to the DB.
My big problem is dealing with properties like prop4 and prop5. This array is being converted to a DynamicJsonArray. To convert it to a primitive array, I'm currently using this:
Array arr = (Array) data["prop4"];
data["prop4"] = arr.Cast<Int32>().ToArray();
The code above works fine and it successfully converts the property value to an integer array that can be sent to the DB. However, when I do it with the string array:
Array arr = (Array) data["prop5"];
data["prop5"] = arr.Cast<string>().ToArray();
The data["prop5"] value isn't changed, and when I inspect it's value, it still points to the type System.Web.Helpers.DynamicJsonArray. Why does this happen?
Also, the thing is that I'm not experienced on working with dynamic objects in C# and I use that because in my situation I do not always know what properties the JSON I'm receiving is going to have. Is there a cleaner way to make this kind of conversion? Actually, is there any need to use dynamic objects to deal with JSONs?
EDIT:
Sorry for being extremely unclear. To clear things up, that's what I'm actually doing:
I'm using a generic function to call a DB procedure with whatever data that comes from the parameter data:
public static IEnumerable<Dictionary<string, object>> CallDBProcedure(string proc, dynamic data)
{
using (NpgsqlConnection conn = new NpgsqlConnection(ConnStr))
{
try
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = proc;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
foreach (string property in data.GetDynamicMemberNames())
{
object propertyValue = data[property];
// The method convertNullValue returns the own value if it's not null
// and returns DBNull.Value if it's null. Every value must be properly
// converted, but I can't directly convert a DynamicJsonArray.
cmd.Parameters.Add(new NpgsqlParameter(property, convertNullValue(propertyValue)));
}
var reader = cmd.ExecuteReader();
return new DrToDictionary().Serialize(reader);
}
}
catch (Exception e)
{
throw e;
}
finally
{
conn.Close();
}
}
}
And then, in order to avoid exceptions, I'm processing data before
I pass it to CallDBProcedure, iterating over the DynamicJsonObject
and converting every DynamicJsonArray inside it to a primitive array:
public static void ProcessData(dynamic data)
{
// Directly using data.GetDynamicMemberNames() and modifiying data
// inside the loop causes an exception. Using a string list instead (hacky code?).
List<string> properties = ((Dictionary<string, object>.KeyCollection) data.GetDynamicMemberNames()).ToList();
foreach (string property in properties)
{
object propertyValue = data[property];
if (propertyValue != null && propertyValue.GetType() == typeof(DynamicJsonArray))
{
Array arr = (Array)data[property];
if (arr.Length == 0)
{
// This works.
data[property] = null;
}
else
{
// Discover the type of my array.
if (arr.GetValue(0) is int)
{
// This works.
data[property] = arr.Cast<Int32>().ToArray();
}
else
{
// This doesn't.
data[property] = arr.Cast<string>().ToArray();
}
}
}
}
}
For now I'm iterating over data twice. I know that there must be an obvious and easy way to make this ugly code cleaner, but I'm just not seeing it.
EDIT2:
A solution that I found was to take only the string arrays and put them inside a different variable. Then I can use them normally. I really don't understand why dynamic objects can change their types in some cases and in other cases they can't.
EDIT3:
Forgot to mention that I'm receiving my json like this: dynamic data = System.Web.Helpers.Json.Decode(json);
It is just reading the json object which is returned from the API.
E.g
You can use
dynamic stuff = JsonConvert.DeserializeObject("{ 'prop1' : 'sometext', 'prop2': '123',
'prop3': 'True'}");
string Prop1= stuff.First.Prop1;
string Prop2= stuff.First.Prop2;
or
// For that you will need to add reference to System.Web.Helpers
dynamic json = System.Web.Helpers.Json.Decode(#""{ 'prop1' : 'sometext', 'prop2': '123',
'prop3': 'True'}"");
Console.WriteLine(json.prop1);
another similar quetion in Stackoverflow as below
How can I parse JSON with C#?
I think the answer to this is pretty obvious, but it's friday so my brain isn't functioning entirely.
I'm working in an asp.net mvc application where I get the id of a selected row. Every time I click a row the id of that row is send to my controller.
What I want to do is output the id just as regular plain text.
This isn't too hard, I use this code:
public string GetInformation(int id)
{
return id.toString();
}
But the user can select multiple rows at once, what happens now is that the id just changes from the first selected row to the second one.
What I want is both the id's to be returned, separated by a comma.
This is what I tried:
public string[] GetInformation(int id)
{
List<string> oud = new List<string>();
oud.Add(id.ToString());
return oud.ToArray();
}
But then it just shows System.String[] as output.
Ok, I'm going to prefix this by saying that I think using sessions for state is generally a bad idea. However, it's an easy way to show state management and retaining the list between requests.
Update your function to this:
public string[] GetInformation(int id)
{
var list = Session["oud"] as List<string>;
if (list == null)
{
list = new List<string>();
Session["oud"] = list;
}
list.Add(id.ToString());
return list.ToArray();
}
Each time you call this method it will get the list from session (user state management). If the list returned from session is null (it's not actually there) we create a new list of strings and add it to the session.
To test this I put the following in an index action of an MVC controller before return View(). When I refresh the page I can see the random id being appended to the list. The same will apply if you make a call from the client.
Random r = new Random();
GetInformation(r.Next(1, 10));
Hope this helps!
Update
Iterating over an array in razor view and printing each item
In your razor view, if you have added this array to your model as MyIds, you could use the following:
#foreach (var id in Model.MyIds)
{
<p>#Html.Raw(id)</p>
}
Update 2
I'm going to make this very easy for you:
public string GetInformation(int id)
{
var list = Session["oud"] as List<string>;
if (list == null)
{
list = new List<string>();
Session["oud"] = list;
}
list.Add(id.ToString());
return string.Join(", ", list);
}
The function now returns a comma separated list of ids that you have passed through.
But then it just shows System.String[] as output.
Well, you're not showing us how you actually output anything. But presumably you're getting a value:
var output = GetInformation(input);
and then trying to write output directly as a string. However, string[] is an array and doesn't have a default string representation. All objects in .NET which don't have a .ToString() implementation inherit their implementation from System.Object, which defaults to outputting the type name.
Instead of outputting the object itself, which is semantically something like this:
Write(output)
(again, semantically, since we don't know how you're actually outputting it, so consider this pseudo-code)
Loop over it for your output:
foreach (var value in output)
Write(value)
You'll have to handle formatting (new lines, delimiters, etc.) for however you want to display the values as a UI concern. But the point, basically, is that you need to loop over your values and output them individually rather than as one big array.
There are shortcuts which will loop over it for you, if you'd like. For example:
Write(string.Join(",", output))
That would "join" all of the strings in output for you, using "," as a delimiter.
Edit: Another problem that you seem to be experiencing is that your method only ever returns a new list of exactly one object:
public string[] GetInformation(int id)
{
List<string> oud = new List<string>();
oud.Add(id.ToString());
return oud.ToArray();
}
This method shouldn't really have the responsibility of maintaining the list. This is because the method itself is stateless, all it really does is convert an integer value to a string. (Which you don't really need a method for, but whatever.) Consuming code should maintain state.
So keep the method as-is:
public string GetInformation(int id)
{
return id.toString();
}
And have the consuming code maintain the collection of values. Something like this:
var output = GetInformation(input);
myOutputs.Add(output);
Where is myOutputs defined? Well, where that state is maintained depends on a lot of things. This is a web application, so state can be an interesting thing. There are many places to maintain it:
Within the consuming method as a method-level variable
Within the consuming class as a class-level value
In session state
In a database
etc.
The overall flow of the logic and the application is going to govern this. For example, if a single instance of the class is maintaining the entire lifetime of this process then you would put it in a class-level value. However, if the value needs to persist across different page requests then you might want to put it in Session State instead. You have a number of options for where to maintain this collection of strings.
Try this:
PSEUDO CODE
public string[] GetInformation(int id)
{
List<string> oud = new List<string>();
oud.Add(id.ToString());
return oud.ToArray();
}
var myResult = GetInformation(1);
Console.WriteLine(string.Join(", ", myResult);
It's more nice to return unformatted data and format it when needed.
public int[] GetInformation(int id)
{
List<int> oud = new List<int>();
oud.Add(id);
return oud.ToArray();
}
var myResult = GetInformation(1);
Console.WriteLine(string.Join(", ", myResult);
I'm writing a Web API ApiController with several PUT methods that receive JSON data. The JSON is not deterministic and hence cannot be hard-mapped to a custom C# object, but needs to be received as Dictionaries/Sequences (Maps/Lists).
I have tried using an IDictionary for the data parm of the PUT method in the controller, and this sort of works -- the data appears to be mapped from JSON to the dictionary. However, it's necessary to declare the dictionary as <String,Object>, and there's no clear way to then retrieve the Object values as their appropriate types. (I've found a few suggested kluges in my searching, but they are just that.)
There is also a System.Json.JsonObject type which I finally managed to get loaded via NuGet, but when I use that the system does not appear to know how to map the data.
How is this typically done? How do you implement an ApiController method that receives generic JSON?
I can see three basic approaches:
Somehow make Dictionary/Sequence work with Object or some such.
Make something like System.Json.JsonObject work, perhaps by swizzling the routing info.
Receive the JSON as a byte array and then parse explicitly using one of the C# JSON toolkits available.
(As to how dynamic the data is, JSON objects may have missing entries or extraneous entries, and in some cases a particular entry may be represented as either a single JSON value or a JSON array of values. (Where "value" is JSON array, object, string, number, Boolean, or null.) In general, except for the array/not array ambiguity, the relation between keys and value types is known.)
(But I should note that this is a large project and I'll be receiving JSON strings from several other components by other authors. Being able to examine the received type and assert that it's as expected would be quite useful, and may even be necessary from a security standpoint.)
(I should add that I'm a relative novice with C# -- have only been working with it for about 6 months.)
You've got to know what kind of data you're expecting, but I have had success doing this in the past using dynamic typing.
Something like this:
[Test]
public void JsonTester()
{
string json = "{ 'fruit':'banana', 'color':'yellow' }";
dynamic data = JsonConvert.DeserializeObject(json);
string fruit = data["fruit"];
string color = data["color"];
Assert.That(fruit == "banana");
Assert.That(color == "yellow");
}
Edit:
You either need to know the type you want to deserialize to beforehand - in which case you can deserialize it to that type immediately.
Or you can deserialize it to a dynamic type, and then convert it to your static type once you know what you want to do with it.
using Newtonsoft.Json;
using NUnit.Framework;
public class DTO
{
public string Field1;
public int Field2;
}
public class JsonDeserializationTests
{
[Test]
public void JsonCanBeDeserializedToDTO()
{
string json = "{ 'Field1':'some text', 'Field2':45 }";
var data = JsonConvert.DeserializeObject<DTO>(json);
Assert.That(data.Field1 == "some text");
Assert.That(data.Field2 == 45);
}
[Test]
public void JsonCanBeDeserializedToDynamic_AndConvertedToDTO()
{
string json = "{ 'Field1':'some text', 'Field2':45 }";
var dynamicData = JsonConvert.DeserializeObject<dynamic>(json);
var data = new DTO { Field1 = dynamicData["Field1"], Field2 = dynamicData["Field2"] };
Assert.That(data.Field1 == "some text");
Assert.That(data.Field2 == 45);
}
}