Extract id from json string [duplicate] - c#

This question already has answers here:
Parse Json string in C#
(5 answers)
Easiest way to parse JSON response
(4 answers)
Closed 5 years ago.
I have the following json string. What is the best way to extract the id from it using c#?
{
"count":1,
"value": [ {
"id":35,
"projectId": "frfsdf-039a-405b-8835-5ddb00cfsdf9f107",
"name":"Default",
"pool":{
"id":1,
"scope":"8850710d-4558-4f08-8064-38000a03d209",
"name":"Default",
"isHosted":false,
"poolType":"automation"
}
}]
}

Using Newtonsoft.Json:
JObejct.Parse(str)["value"].First()["id"].Value<string>()
Newtonsoft is pretty much the way to handle json in c#.
Note that you can have more then one item in the array. This code takes the first.

The developer-time-cheapest way would be to use C# dynamic
using Newtonsoft.Json;
Int32 GetId()
{
String jsonStr = "{ \"count\":...";
dynamic jsonBlob = JObject.Parse( jsonStr );
return jsonBlob.value[0].id;
}
Note I'm personally opposed to using dynamic because you lose compile-time type-safety, and dynamic is somewhat expensive for single-use operations - so you might want to process it using Json.NET's own token objects:
JObject root = JObject.Parse( jsonStr );
JToken idToken = root.Properties["value"].GetChildren().First().Properties["id"];
return idToken.ToObject<Int32>();
Finally, you could always define your own class and deserialize that way:
class Foo {
public Int32 Count { get; set; }
public FooValue[] Value { get; set; }
}
class FooValue {
public Int32 Id { get; set; }
public Guid ProjectId { get; set; }
public String Name { get; set; }
}
Foo foo = JsonConvert.Deserialize<Foo>( jsonStr );
return foo.Value[0].Id;
If the JSON format will always be consistent and you won't be processing any other JSON then you can avoid the dependency on Newtonsoft.Json (Json.NET) by using a regular-expression or even trivial string processing:
Int32 idIdx = jsonStr.IndexOf("\"id\":");
if( idIdx == -1 ) return null;
Int32 commaIdx = jsonStr.IndexOf(",", idIdx);
if( commaIdx == -1 ) return null;
return jsonStr.Substring( idIdx, commaIdx - idIdx );

Related

Avoid re-serializing of a json string [duplicate]

This question already has answers here:
Is there an equivalent for JRaw in System.Text.Json
(1 answer)
How can I serialize a literal JSON value with System.Text.Json?
(1 answer)
Closed 5 months ago.
Is there a way to selectively exclude a field from re-serialization, if it already contains a valid json string?
Here is what I am attempting.
First, I define a class of the result row I recieve from my database.
public class objectToSerialize
{
public string identifier { get; set; }
public string jsonPayload { get; set; }
public objectToSerialize()
{
identifier = String.Empty;
jsonPayload = String.Empty;
}
}
Then I run my query and add all the results to a list.
List<objectToSerialize> listOfobjectToSerialize = new List<objectToSerialize>();
[...]
while(SqlDataReader.Read())
{
[...]
listOfobjectToSerialize.add(objectToSerialize)
}
Finally, I return my list as an APS.NET OkObjectResult, which serializes the list to JSON by default.
[...]
return (ActionResult)new OkObjectResult(listOfobjectToSerialize);
The jsonPayload already contains a json string, that should not be re-serialized again when returning the result.
So far I have deserialized the jsonPayload to an object, which was then serialized fine, but I would like to avoid that unnessesary step.
I have tried using the field attributes [JsonIgnore] and [NonSerialized()] but they remove the field from the result altogether.
Is there a way to include the jsonPayload string as-is?
Here is an example:
objectToSerialize.identifier = 123;
objectToSerialize.jsonPayload = #"
{
"ThisIsAKey" : "ThisIsAValue"
}"
Desired output:
{
"identifier" : 123,
"jsonPayload" : {
"ThisIsAKey" : "ThisIsAValue"
}
}
Actual output:
{
"identifier" : 123,
"jsonPayload" : "{
\"ThisIsAKey\" : \"ThisIsAValue\"
}"
}
So far I am trying to write my own custom JsonConverter.
this will not be even compiled
objectToSerialize.jsonPayload = #"
{
"ThisIsAKey" : "ThisIsAValue"
}"
if you want Desired output
objectToSerialize.jsonPayload = new
{
ThisIsAKey = "ThisIsAValue"
};
but as I guess your jsonPayload is a string , so you can only do this
objectToSerialize.jsonPayload = #"{
""ThisIsAKey"" : ""ThisIsAValue""
}";
leave like this, otherwise you are just looking for a trouble, you will not be able to deserialize jsonPayload to string when you get your response.
If it is already the JSON, we could give a try to plain/text as the content type of the response.
May be,
Request.Content = "text/plain";
return Content(alreadyCreatedJson);

Trying to get first object out of an json array in C#

I'm trying to get the first object out of a json array in c#. The Array looks something like this:
[
{
"name": "Joe",
"id": 1
},
{
"name": "Melinda"
"id": 2
}
]
I didn't find a suitable way to do this so I'm asking here. I'm using System.Text.JSON. I'm currently using this code:
class Program
{
public static void Main(String[] args)
{
HttpClient client = new HttpClient();
string url = "example.com";
string json = client.GetStringAsync(url).ToString()!;
Sensor sensor = JsonSerializer.Deserialize<Sensor>(json)!;
Console.WriteLine(sensor.id);
}
}
public class Sensor
{
public string? id { get; set; }
}
Now, unsurprisingly, when i run this code, System.Text.Json throws an error, but i cant decipher what exactly caused it (prbl bc im stupid):
inner exception System.Text.Json.JsonReaderException: 'S' is an invalid start of a value. LineNumber: 0 | BytePositionInLine: 0.
at System.Text.Json.ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes)
at System.Text.Json.Utf8JsonReader.ConsumeValue(Byte marker)
at System.Text.Json.Utf8JsonReader.ReadFirstToken(Byte first)
at System.Text.Json.Utf8JsonReader.ReadSingleSegment()
at System.Text.Json.Utf8JsonReader.Read()
at System.Text.Json.Serialization.JsonConverter`1.ReadCore(Utf8JsonReader& reader, JsonSerializerOptions options, ReadStack& state)
Is there an easy way to do this with System.Text.Json or Newtonsoft.Json?
Thx
You should deserialize json string as new List() and then you can find first element of the list using FirstOrDefault() method as follow :
class Sensor
{
public int Id { get; set; }
public string Name { get; set; }
}
public Sensor GetFirstElementOfJsonArray(String data)
{
JsonSerializerOptions options = new JsonSerializerOptions(){
PropertyNameCaseInsensitive = true };
List<Sensor> sensorList=JsonConvert.Deserialize<List<Sensor>>(data,options);
return sensorList.FirstOrDefault();
}
I think , it will the answer of your question
An approach very close to yours:
using System;
using System.Text.Json;
public class Program
{
public static readonly string data = #"[{""name"": ""Joe"",""id"": 1},{""name"": ""Melinda"", ""id"": 2 }]";
public static void Main()
{
// System.Text.Json defaults to case-sensitive property matching,
// so I need to switch this to insesitive, if the model adheres
// to C# naming convention ( Props start with capital letter)
JsonSerializerOptions jso = new JsonSerializerOptions(){ PropertyNameCaseInsensitive = true };
// We are deserializing an Array vv
var sensors = JsonSerializer.Deserialize<Sensor[]>(data, jso);
// I do an output for demonstration purposes.
// You'd want to check for null and size>0 and then use the first element.
foreach( var sensor in sensors )
{
Console.WriteLine($"{sensor.Id:#0} : {sensor.Name}");
}
}
}
public class Sensor
{
public int Id {get; set;}
public string Name {get; set;}
}
See in action: https://dotnetfiddle.net/t7Dkh8
Another Idea would be to incrementally parse, which is beneficial if the array is long and you only need the first element.
See Incremental JSON Parsing in C#
(Needs NewtonSoft, though)
Another remark that I and Jon Skeet already made in comments:
The errormessage you are getting
'S' is an invalid start of a value. LineNumber: 0 ...
hints towards that the received string might not actually be valid json. So you might want to investigate this, too.
You could set a breakpoint and look into the value using the debugger,
just spit it out to a text file or if you have logging, log it.
There are two issues that I see in your question. The first is that the id field in the json is not a string but an integer. So you either need to change your json so that it looks like this:
[
{
"name": "Joe",
"id": 1,
...
or update your Sensor class to look like this:
public class Sensor
{
public int id { get; set; }
public string? name { get; set; }
}
Once you do that though the other issue is that your json is not an object, but an array. so your code needs to look more like this:
HttpClient client = new HttpClient();
string url = "example.com";
string json = client.GetStringAsync(url).ToString()!;
var sensors = JsonSerializer.Deserialize<IEnumerable<Sensor>>(json)!;
Console.WriteLine(sensors.First().id);
So serialize the json into a collection (IEnumerable), then you can query that collection to get whatever data you need. Also, I don't know if that was just representative data, but in your json example above, there is a comma missing after "Melinda" in the json.
you need to deserialise to a class:
public class Sensor {
public int Id { get; set; }
public string Name { get; set; }
}
JsonSerializer.Deserialize<Sensor>(json)

How do I get a value from a Json in .NET 3.5 C#?

On .NET 4.5 I was getting by
string respString= response.Body; // { "name":"John", "age":30, "car":null}
var respObj= JsonConvert.DeserializeObject<dynamic>(respString);
In this case, I was able to create a dynamic object of each property.
However, I have dropped to .NET 3.5, and the dynamic option is not available. How can
I get each property as
string gottenName= respObj.name;
double gottenAge = respObj.age;
etc.
Thank you guys kindly!
Visit a JSON to C# class conversion service, eg: https://www.jsonutils.com/
Paste in the JSON:
{ "name":"John", "age":30, "car":null}
It will generate a Class:
public class Example
{
public string name { get; set; }
public int age { get; set; }
public object car { get; set; }
}
Then you don't need dynamic:
Example respObj= JsonConvert.DeserializeObject<Example>(respString);
You can also parse to C# object using newtonsoft.dll
code will be
JObject jsonResponse = JObject.Parse(respString);
//you can access name value using
var nameValue= (string)jsonResponse["name"]
//respString is jsonstring

JSON.NET deserialize JSON then format string [duplicate]

This question already has answers here:
running a transformation on a Json DeserializeObject for a property
(2 answers)
Closed 3 years ago.
I have the following JSON:
{
"lastOcurrences":[
{
"myString":"16726354"
},
{
"myString":"66728744"
},
{
"myString":"91135422"
}
]
}
and I have a class to deserialize it on:
public class JsonObject
{
public List<LastOcurrence> LastOcurrences { get; set; }
}
public class LastOcurrence
{
public string MyString { get; set; }
}
Upon deserializing it with JsonConvert.DeserializeObject<T>(json), I'd like to be able to format the string myString, to store 167-263-54, instead of 16726354.
What solution would please my soul: Using attributes on the properties, something of the likes of JsonConverter, but...
What i'd like to avoid doing: I would not like to use reflection to iterate through every property, only to then read the attribute and apply the formatting. Is there any way of doing this 'automatically' with JsonConvert?
One possible solution is to use custom getters and setters for this and when it is deserialized you keep the raw data stored. This will do JIT formatting. Depending on the usage of this data this could be much quicker however if there are a lot of repeated reads of the same data then this may be a bit slower.
public class LastOcurrence
{
private string _myString;
public string MyString
{
get { return Regex.Replace(_myString, #"^(.{ 3})(.{ 3})(.{ 2})$", "$1-$2-$3"); }
set { _myString = value; }
}
}

Deserialize JSON string in to multiple C# objects

I have a JSON string in below format for which I want to deserialize it into C# List. But the record number "1","2","3" (it can be upto 1,2,3...n depends on the json response each time) in JSON restricting me to deserialize it into C# object using Newtonsoft.Json
{
"1":{
"UID":"1",
"LICENCENO":"licenseno",
"NAME":"ABC"
},
"2":{
"UID":"2",
"LICENCENO":"licenseno",
"NAME":"PQR"
},
"3":{
"UID":"3",
"LICENCENO":"licenseno",
"NAME":"XYZ"
}
}
I am using below code for deserialization
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<List<DriverMaster>>(json);
I have DriverMaster class created as-
public class DriverMaster
{
public string UID { get; set; }
public string LICENCENO { get; set; }
public string NAME { get; set; }
}
Deserialization line giving unhandled exception, I know I am doing it in wrong way, because DriverMaster json object cannot be extracted into c# directly without doing something to record number 1,2,3...n in c#. Can anyone please help me to sort it out? Thanks in advance.
You were close:
var result = JsonConvert.DeserializeObject<Dictionary<string, DriverMaster>>(json)
.Select(x => x.Value)
.ToList();
Solution.
Change your code to use...
var result = JsonConvert.DeserializeObject<Dictionary<int, DriverMaster>>(json);
Explaination
The type is not the same... The List<DriverMaster>type will convert to JSON like so...
{
"1":
{
"DriverMaster": {
"UID":"1",
"LICENCENO":"licenseno",
"NAME":"ABC"
}
}
}
This doesn't match what you showed in your question...
The type that you are looking for is actually Dictionary<int, DriverMaster>, which is a key/value pair which will output a JSON string like so
{
"1": { ... },
"2": { ... },
"3": { ... }
}
In order to fix that, you need to use the Dictionary<int, DriverMaster> type instead.
For these types of things I like to use the often overlooked feature of JToken.SelectTokens. This function allows you to select tokens within a json string and permits the use of wildcards.
Here's some code that will deserialize your sample by selecting past the 1,2,3...N in the json:
public static IEnumerable<DriverMaster> Deserialize(string json)
{
return JToken.Parse(json).SelectTokens("*")
.Select(jToken => jToken.ToObject<DriverMaster>());
}
The * basically says to select all tokens after the root, so it's selecting the values associated with 1, 2, 3.. etc... Here's another SO answer that shows a more complicated usage of the SelectTokens method.
You need to use
public class DriverMaster
{
public string UID { get; set; }
public string LICENCENO { get; set; }
public string NAME { get; set; }
}
public class Root
{
[JsonExtensionData]
public IDictionary<string,JToken> Data {get;set;}
}
and
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<Root>(json);
If you want to have result as List, you can parse the result as.
var list = new List<DriverMaster>();
foreach(KeyValuePair<string, JToken> token in result.Data)
{
list.Add(token.Value.ToObject<DriverMaster>());
}
That would give you the desired result as
1 licenseno ABC
2 licenseno PQR
3 licenseno XYZ

Categories