简体   繁体   中英

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

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.

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

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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM