I want to write a PowerShell function in C#. During the process I receive a string with JSON content.
My sample json content is:
string json = "{'TestNr':{'Name':'CSHARP', 'Description':'Test Descriptiopn'}}"
This string should be converted to a PSObject just like ConvertFrom-Json would do.
I was trying to create an object with below lines. It works but it would require a lot of manual scripting especially if the JSON string becomes longer.
PSObject obj = new PSObject();
obj.Properties.Add(new PSNoteProperty("Head", "Children"));
I tried also the below line:
obj = (PSObject)TypeDescriptor.GetConverter(typeof(PSObject)).ConvertFromString(json);
For this I get however the error (I run the function in PowerShell 7):
TypeConverter cannot convert from System.String.
There are two ways you can parse the string in C# that would be the easiest to go with.
public class MyClass
{
public TestNRClass TestNR { get; set; }
}
public class TestNRClass
{
public string Name { get; set; }
public string Description { get; set; }
}
// In the main,
string json = #"{""TestNr"":{""Name"":""CSHARP"", ""Description"":""Test Descriptiopn""}}";
MyClass jobj = JsonConvert.DeserializeObject<MyClass>(json);
Console.WriteLine(jobj.TestNR.Name);
This is with the strong typed class object. This is what you should be using in C#.
Other way is to get an object
string json = #"{""TestNr"":{""Name"":""CSHARP"", ""Description"":""Test Descriptiopn""}}";
JObject obj = JObject.Parse(json);
Console.WriteLine(obj.ToString());
Console.WriteLine(obj["TestNr"]["Name"].ToString());
// You can also add more keyValuePair
obj["NewVariable"] = "stest";
Console.WriteLine(obj.ToString()); // Shows the new item as well.
Related
So I have a JSON string where I just want to read a specific value. How do I just pick "Read me please!" from string below?
var readString = /*Read me please!*/
JSON string:
"{\"aString\":\"Read me please!\"}"
For better understanding, how do I do the same here? (just "Read me please!"):
"{\"Result\":
{
\"aString\":\"Read me please!\",
\"anotherString\":\"Dont read me!\"
}
}"
If both alternative have different solution I would like to know both.
PS: I do not wish to save the value into object/class or so. Just temporary inside var readString.
You could write a model:
public class MyModel
{
public string AString { get; set; }
}
and then use a JSON serializer such as Json.NET:
string readString = "{\"aString\":\"Read me please!\"}";
MyModel model = JsonConvert.DeserializeObject<MyModel>(readString);
Console.WriteLine(model.AString);
If you don't want to use third party solutions you could use the built-in JavaScriptSerializer class:
string readString = "{\"aString\":\"Read me please!\"}";
MyModel model = new JavaScriptSerializer().Deserialize<MyModel>(readString);
Console.WriteLine(model.AString);
Now assuming you want to handle your second JSON string you could simply adapt your model:
public class Wrapper
{
public MyModel Result { get; set; }
}
public class MyModel
{
public string AString { get; set; }
public string AnotherString { get; set; }
}
and then deserialize to this wrapper class:
string readString = ... the JSON string in your second example ...;
Wrapper wrapper = JsonConvert.DeserializeObject<Wrapper>(readString);
Console.WriteLine(wrapper.Result.AString);
Console.WriteLine(wrapper.Result.AnotherString);
UPDATE:
And if you don't want to deserialize to a model you could directly do this:
string readString = "{\"aString\":\"Read me please!\"}";
var res = (JObject)JsonConvert.DeserializeObject(readString);
Console.WriteLine(res.Value<string>("aString"));
or with the built-in JavaScriptSerializer class:
string readString = "{\"aString\":\"Read me please!\"}";
var serializer = new JavaScriptSerializer();
var res = (IDictionary<string, object>)serializer.DeserializeObject(readString);
Console.WriteLine(res["aString"]);
var readString = JObject.Parse(str)["aString"];
Or for your second example:
var readString2 = JObject.Parse(str2)["Result"]["aString"];
Json.NET also provides a JSON reader if you don't want to deserialize the whole thing. For example:
string json = "{\"Result\": { \"aString\":\"Read me please!\", \"anotherString\":\"Dont read me!\" } }";
using (var reader = new JsonTextReader(new StringReader(json)))
{
while (reader.Read())
{
if (reader.TokenType == JsonToken.PropertyName && (string)reader.Value == "aString")
{
reader.Read();
Console.Write(reader.Value);
break;
}
}
}
Console.ReadKey();
You have to use Newtonsoft (JSON.NET) to accomplish that. Then, you can access your json property this way:
var obj = JsonConvert.DeserializeObject(yourJson);
Console.WriteLine(obj.Result.aString);
I played around with writing a generic method that can read any part of my json string. I tried a lot of the answers on this thread and it did not suit my need. So this is what I came up with. I use the following method in my service layer to read my configuration properties from the json string.
public T getValue<T>(string json,string jsonPropertyName)
{
var parsedResult= JObject.Parse(json);
return parsedResult.SelectToken(jsonPropertyName).ToObject<T>();
}
and this is how you would use it :
var result = service.getValue<List<string>>(json, "propertyName");
So you can use this to get specific properties within your json string and cast it to whatever you need it to be.
so i want to get bitcoin price from a URL and see it in a label in my form.
URL
i tried to make a class for it with the code
public string price { get; set; }
but i don't know what to do after that, i searched a lot in google but they all show the result in list and etc
To deserialize, first you need to make a class with the attributes the JSON has. This page will help you a lot in that.
Once you have a class, you need to deserialize your JSON into that class. In C# I like to use JsonConvert from the library Newtonsoft.Json, you need to import it.
The method that deserializes it is JsonConvert.DeserializeObject.
One little example, let's say your class is called Bitcoin, then you would have to do it that way :
var myBitcoin = JsonConvert.DeserializeObject<Bitcoin>(yourJson);
EDIT: To pull your json from an URL you can use Webclient DownloadString method.
var myjson = new WebClient().DownloadString("url");
This post may also help you.
This should be your class.
public class APIResponse
{
public string symbol { get; set; }
public string price { get; set; }
}
Then in your function add these lines.
APIResponse response = new APIResponse();
response = JsonConvert.DeserializeObject<APIResponse>();
myPriceLabel.Text = response.price;
What did we do? We created a C# model same as the Json Data model and we took JSON data and converted it to APIResponse type so we can access it and use it as we like.
It can be achieved simply by converting the Json with generic object
var myBitcoin = JsonConvert.DeserializeObject<object>(yourJson);
thank you all for answering but i found the solution!
the code should be like this
string url = "https://api.binance.com/api/v3/ticker/price?symbol=BTCUSDT";
using (WebClient wc = new WebClient())
{
var json = wc.DownloadString(url);
JavaScriptSerializer oJS = new JavaScriptSerializer();
PriceClass obj = new PriceClass();
obj = oJS.Deserialize<PriceClass>(json);
BTCPrice_Label.Text = obj.price;
}
and the class should be like this
using System;
public class PriceClass
{
public string symbol { get; set; }
public string price { get; set; }
}
I'm having troubles with some Deserialization because I'm not receiving an object like I'm used to but an array. Lets to the code, how I've being doing it:
JSON received:
[{"gcm_regID":"fsdf2156fw62f1wfwe512g"}]
Deserialization
var result = JsonConvert.DeserializeObject<Gcm>(response);
Handlers Tried:
public class Gcm
{
public List<Gcm_reg> gcm_regID { get; set; }
}
public class Gcm_reg
{
public string gcm_regID { get; set; }
}
I've tried just the Gcm_reg as well and nothing seems to work. How can I deserialize this? By the way, I'm using the newsoft JSON.
Best regards,
IEnumerable<Gcm_reg> result = JsonConvert.DeserializeObject<IEnumerable<Gcm_reg>>(response);
You can deserialize the object as an array or IEnumerable
Object should be like
public class Gcm
{
public string gcm_regID { get; set; }
}
So Try it
var result = JsonConvert.DeserializeObject<IEnumerable<Gcm>>(response);
You can directly generate classes from Json by using link
To create same type of object
var outputList = new List<Gcm>();
//loop through this part based on number of input
var itemToAdd = new Gcm();
itemToAdd .regID = 'something';
outputList.Add(itemToAdd );
and send outputList to server.
I am connecting you Google Places API to retrive results in the form of a JSON string. You can view the complete format of the string Here.
If you a look at it you will see that the actual results array starts after two elements which are html_attributions and next_page_token.
So When i try to deserialize it in this way:
var serializer = new JavaScriptSerializer();
var arr= serializer.Deserialize(result,typeof(string[]));
I get an empty array.
My question is how is there a way i can separate html_attributions and next_page_token fields and the pass the valid results array from the string to be deserialized?
I don't understand the part where you wish to seperate the html_attributions and the next_page_token.
Wouldn't it be sufficient to just deserialize the response with whatever properties that you need?
For example, you can deserialize the response to only retrieve the values that you desire;
// I represent the wrapper result
class Result
{
public List<string> html_attributions { get; set; }
public string next_page_token { get; set; }
public List<ResultItem> results { get; set; }
}
// I represent a result item
class ResultItem
{
public string id { get; set; }
public string name { get; set; }
}
// the actual deserialization
Result Deserialize(string json)
{
var serializer = new JavaScriptSerializer();
return serializer.Deserialize(json, typeof(Result));
}
Edit:
The reason that your deserialization doesn't return you a array of strings is because the response that you retrieve is infact an object and not an array, however the parameter within that object which is named results is an array. In order for you to deserialize more properties you'll have to define them in your "ResultItem" class, sorry for my poor naming here.
For instance, if you'd wish to also retrieve the icon property per result you'll have to add a property named "icon" of type string.
Meanwhile the property "photos" is an array, in order to deserialize it you'll have to create another class and add a property of type list/array of that newly created class, and it has to be named "photos" unless you use a different serializer or use DataContract and DataMember attributes (using the Name property for field mapping).
// the representation of a photo within a result item
class Photo
{
public int height { get; set; }
public List<string> html_attributions { get; set; }
public string photo_reference { get; set; }
public int width { get; set; }
}
// I represent a result item
class ResultItem
{
public string id { get; set; }
public string name { get; set; }
// the added icon
public string icon { get; set; }
// the added photos collection, could also be an array
public List<Photo> photos { get; set; }
}
Just look at the JSON result to figure out what other properties that you might want to add, for instance the "scope" property is an string whilst the "price_level" is an integer.
If I understand your comment correctly you're only interested in the actual results, you'll still have to deserialize the response correctly with its wrapper.
// the actual deserialization
List<ResultItem> Deserialize(string json)
{
var serializer = new JavaScriptSerializer();
var result = serializer.Deserialize(json, typeof(Result));
return result.results;
}
Edit2:
If you really want a string[] as a result you could simply take use of System.Linq using the code above.
string[] stringArray = result.results.Select(r => string.Format("id:{0} - name:{1}", r.id, r.name)).ToArray();
Edit3:
Instead of using the JavascriptSerializer you could use JObject functionality which can be found in the Newtonsoft.Json.Linq library.
var jsonObject = JObject.Parse(json);
string[] results = jsonObject.SelectTokens("results").Select(r => r.ToString()).ToArray();
This will give you an array of strings where each value within the array is the actual json string for each result.
If you however would like to query for the coordinates only:
var jsonObject = JObject.Parse(json);
var coordinates = jsonObject["results"]
.Select(x => x.SelectToken("geometry").SelectToken("location"))
.Select(x => string.Format("{0},{1}", (string)x.SelectToken("lat"), (string)x.SelectToken("lng")))
.ToArray();
This would give you an array of coordinates, eg:
[
"-33.867217,151.195939",
"-33.866786,151.195633",
...
]
Whatever approach you choose you'll be able to accomplish same results using either Newtonsoft or the .net serializer, whilst the Newtonsoft approach would allow you to query without creating strong types for deserialization.
I don't find the point of "[...] pass the valid results array from the string to be deserialized".
Maybe you need to switch to JSON.NET and do something like this:
// You simply deserialize the entire response to an ExpandoObject
// so you don't need a concrete type to deserialize the whole response...
dynamic responseEntity = JsonConvert.DeserializeObject<ExpandoObject>(
googlePlacesJson, new ExpandoObjectConverter()
);
// Now you can access result array as an `IEnumerable<dynamic>`...
IEnumerable<dynamic> results = responseEntity.results;
foreach(dynamic result in results)
{
// Do stuff for each result in the whole response...
}
I used json2csharp to get this:
http://pastebin.com/pbDYCrWk
From that, I wish to get the title that is held in the Oembed section.
I'm using this code:
string url = "http://www.reddit.com/r/all.json";
string jsonText = await DoStuff(url);
var json = Newtonsoft.Json.JsonConvert.SerializeObject(jsonText);
var deserializeObject = Newtonsoft.Json.JsonConvert.DeserializeObject<Page.Oembed>(json);
string test = deserializeObject.title;
And I assumed it would work, however on the line with the deserializeObject variable, I get an error saying it can't do it.
I tried using Page.RootObject however it doesn't work either, and I assumed it would since it seems to be the root.
What am I doing wrong and how can I solve it? Thanks.
If you used Json2CSharp then it is RootObject:
public class RootObject
{
public string kind { get; set; }
public Data data { get; set; }
}
Should be:
var deserializeObject = Newtonsoft.Json.JsonConvert.DeserializeObject<JuicyReddit.RootObject>(json);