Kamran Shahid
Kamran Shahid

Reputation: 4124

Converting Newtonsoft code to System.Text.Json which is using Newtonsoft.Json.Linq.JObject

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"}

Upvotes: 3

Views: 1390

Answers (1)

dbc
dbc

Reputation: 116785

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.

Upvotes: 3

Related Questions