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
CodePudding user response:
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
CodePudding user response:
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.
CodePudding user response:
you need to deserialise to a class:
public class Sensor {
public int Id { get; set; }
public string Name { get; set; }
}
JsonSerializer.Deserialize<Sensor>(json)