Home > Back-end >  Trying to get first object out of an json array in C#
Trying to get first object out of an json array in C#

Time:05-18

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)
  • Related