Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to convert BinaryData into a dictionary or a dynamic type #113477

Open
JoshLove-msft opened this issue Mar 13, 2025 · 3 comments
Open

Comments

@JoshLove-msft
Copy link
Contributor

JoshLove-msft commented Mar 13, 2025

There are cases where you are dealing with a BinaryData instance which contains some data following a known JSON schema under a given property, e.g.

{
  "pets": [
    {
      "id": 1,
      "name": "Buddy",
      "type": "Dog",
      "age": 5
    },
    {
      "id": 2,
      "name": "Mittens",
      "type": "Cat",
      "age": 3
    }
  ],
  "next": "https://api.example.com/pets?page=2"
}

I want to deserialize everything under "pets" into a List<Pet>. There isn't a simple way to do this with the BinaryData API. In Azure, there is an extension method that allows you converting BinaryData to a dynamic type. There is also another extension method that allows converting to a dictionary of string, object here. Having this ability outside of Azure would be helpful.
Ultimately, I'd like to be able to do this:

List<Pet> pets = binaryData["pets"].ToObjectFromJson<List<Pet>>();

or how it would look with the Azure extension method:

List<Pet> pets = binaryData.ToDynamicFromJson().Pets.ToObjectFromJson<List<Pet>>();

As a workaround, I was able to use JsonNode, but it feels like there is something missing from the BinaryData API:

var node = JsonNode.Parse(page.GetRawResponse().Content.ToString())!;
List<Pet> pets = node["pets"].ToObjectFromJson<List<Pet>>();
@dotnet-policy-service dotnet-policy-service bot added the untriaged New issue has not been triaged by the area owner label Mar 13, 2025
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis
See info in area-owners.md if you want to be subscribed.

@eiriktsarpalis eiriktsarpalis added this to the Future milestone Mar 13, 2025
@eiriktsarpalis eiriktsarpalis removed the untriaged New issue has not been triaged by the area owner label Mar 13, 2025
Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-memory
See info in area-owners.md if you want to be subscribed.

@am11
Copy link
Member

am11 commented Mar 14, 2025

One option is to access content directly from JsonNode without making content copies, another option is to deserialize the JsonNode:

using System;
using System.Text.Json;
using System.Text.Json.Nodes;

// <PackageReference Include="System.Memory.Data" Version="9.0.3" />

ReadOnlySpan<byte> json = """
  {
    "pets": [
      {
        "id": 1,
        "name": "Buddy",
        "type": "Dog",
        "age": 5
      },
      {
        "id": 2,
        "name": "Mittens",
        "type": "Cat",
        "age": 3
      }
    ],
    "next": "https://api.example.com/pets?page=2"
  }
"""u8;

BinaryData binaryData = new BinaryData(json.ToArray());

JsonNode? rootNode = JsonNode.Parse(binaryData.ToMemory().Span);

// optin 1: access JSON array via node
JsonArray? petsArray = rootNode?["pets"]?.AsArray();
if (petsArray is not null)
{
    foreach (JsonNode? petNode in petsArray) Console.WriteLine(petNode);
}

// option 2: deserialize to concrete type
List<Pet>? pets = JsonSerializer.Deserialize<List<Pet>>(rootNode?["pets"]);
if (pets is not null)
{
    foreach (var pet in pets) Console.WriteLine(pet);
}

file record Pet(int Id, string Name, string Type, int Age);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants