2

I need help in converting following code which is using newtonsoft to System.Text.Json

string myList = null!;
string jSon = /* From some source */;
object jsonObject = JsonConvert.DeserializeObject(jSon, typeof(object));

// Loop through the keys
foreach (var jsonList in ((Newtonsoft.Json.Linq.JObject)(jsonObject)))
{                   
    if (jsonList.Key == "myKey")
    {                       
        foreach (object o in (jsonList.Value.ToArray()))
        {                           
            myList += o.ToString().ToUpper() + ',';
        }
    }
}

json like:

{"myKey":["fir","dsdsd"],"status":"ok"}
Kamran Shahid
  • 3,954
  • 5
  • 48
  • 93

1 Answers1

2

With System.Text.Json, you can parse arbitrary JSON using either the JsonDocument or JsonNode document object models. The differences are:

  • JsonNode is modifiable and is, in my opinion, easier to work with as it most closely resembles Newtonsoft's LINQ to JSON model. It was added in .NET 6.
  • JsonDocument is read-only, but may be a little more memory-efficient in parsing huge JSON files. It was introduced as part of the original System.Text.Json API in .NET Core 3.0.

Thus, using JsonNode, your code can be rewritten as follows:

static string? QueryJson(string json, string myKey, bool addComma = false)
{
    // Parse to a JsonNode and cast to JsonObject.  An exception is thrown if not an object
    var node = JsonNode.Parse(json)!.AsObject(); 
    
    // Query the array of strings
    var query = (node[myKey] as JsonArray)?.Select(i => i?.ToString().ToUpper());
    if (query == null)
        return null; // Return null if key not found as per original code
    if (addComma)
        query = query.Concat(new [] { "" });

    // Join the string array into a single comma-separated string
    return string.Join(',', query);
}

And here is a version of the same logic using JsonDocument:

static string? QueryJsonWithJsonDocument(string json, string myKey, bool addComma = false)
{
    // Parse to a JsonNode and cast to JsonObject.  An exception is thrown if not an object
    using var doc = JsonDocument.Parse(json);

    // Query the array of strings
    var query = doc.RootElement.Get(myKey)?.EnumerateArray().Select(e => e.GetString()?.ToUpper());
    if (query == null)
        return null; // Return null if key not found as per original code
    if (addComma)
        query = query.Concat(new [] { "" });

    // Join the string array into a single comma-separated string
    return string.Join(',', query);
}

This uses the following extension method from here to check for missing or null properties:

public static partial class JsonExtensions
{
    public static JsonElement? Get(this JsonElement element, string name) => 
        element.ValueKind != JsonValueKind.Null && element.ValueKind != JsonValueKind.Undefined && element.TryGetProperty(name, out var value) 
            ? value : (JsonElement?)null;
}

Notes:

  • You tagged your question . This version goes out of support in about a month, on December 13, 2022. If you are using this version you will need to use JsonDocument since JsonNode was introduced in .NET 6.

  • JsonDocument is disposable, and should be disposed to ensure that pooled memory is returned to the system. JsonNode is not disposable.

  • It will be more efficient to use string.Join() than manually building a comma-separated string using multiple string additions.

  • Your current code adds a trailing comma to the string: FIR,DSDSD,. This looks like a bug, but if you want that you can make string.Join() add a trailing comma by adding an extra empty string to the query.

Demo fiddle here.

dbc
  • 104,963
  • 20
  • 228
  • 340
  • thanks @dbc. i know 3.1 is expiring but there are places where even 2.1/2.2 is used in production. luckily my this logic is in .net 6 solution so i will use the JsonNode solution. about the trailing comma i have a legacy code where first they create string like initial solution then removed it via extension method :) – Kamran Shahid Nov 02 '22 at 20:38