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 JSON support #789

Open
paule96 opened this issue Apr 8, 2024 · 9 comments
Open

Add JSON support #789

paule96 opened this issue Apr 8, 2024 · 9 comments
Assignees
Labels

Comments

@paule96
Copy link

paule96 commented Apr 8, 2024

1. Description

It would be nice to directly access JsonElements / JsonObjects properties and use them in queries. (for simplification I will only use JsonElements from System.Text.Json in the following issue. But Newtonssoft.json is important too)

So that you can easily do something like:

var jsonDocument = JsonDocument.Parse(@"[
    {
        ""first"": 1,
        ""City"": ""Paris"",
        ""third"": ""012-04-23T18:25:43.511Z""
    }]");
jsonDocument.RootElement.Where("City ==\"Paris\"");

Currently, it will tell you that the JsonElement doesn't contain the property City. What is true but also not.
The correct C# linq Query would look like:

jsonDocument.RootElement.Where(e => e.GetProperty("City").GetRawText() == "Paris");

It would be nice to have a default translator for JsonElement to "normal" dynamic linq queries.
It would be especially useful when the Expression and the JSON is not defined.

I'm aware of the issue #415. He showed a way how you could first convert the JsonElement to a dynamic type. But that would mean to create always a new dynamic type if you do not know the type. And technically I know the type, but the type is not nice to query with Linq. (JsonElement) This solution makes it also impossible to cache the compiled query, because I don't know the JSON structure and that means all the time I need to change the input parameter of my expression, which forces a recompile.

So for me the best solution would be if dynamicLinq could detect that the starting parameter of the expression is a JsonElement and then restructur internally the Expressions to the correct format.

@StefH StefH self-assigned this Apr 8, 2024
@StefH StefH added the feature label Apr 8, 2024
@StefH
Copy link
Collaborator

StefH commented Apr 8, 2024

Thanks for the idea.

A way to implement this is to create projects which depend on System.Text.Json and Newtonssoft.Json which provide extension methods like Where on JsonDocument and JObject.

@paule96
Copy link
Author

paule96 commented Apr 8, 2024

@StefH you mean something like:

public static IQueryable<T> Where(this IQueryable<T> source, string expression){
   // TODO: parse expression
  // TODO: Rebuild all Property access expression to access `GetProperty(propertName)`
  // TODO: return result
} 

@StefH
Copy link
Collaborator

StefH commented Apr 8, 2024

More like this:

public static IQueryable<T> Where(this JsonDocument source, string expression)
{
}

Or

public static IQueryable<T> Where(this IObject source, string expression)
{
}

@paule96
Copy link
Author

paule96 commented Apr 8, 2024

but shouldn't the base of the Extension method be something enumerable?
Also a JsonDocument can also be {}, that would result in an error I guess.
Shouldn't it be more like:

public static IQueryable<ArrayEnumerator> Where(this ArrayEnumerator source, string expression)
{
}

Then you can access over Current the current JsonElement and test the expression.

and on the user code side it would look like:

var jsonDocument = JsonDocument.Parse(@"[
    {
        ""first"": 1,
        ""City"": ""Paris"",
        ""third"": ""012-04-23T18:25:43.511Z""
    }]");
if(jsonDocument.RootElement.ValueKind != JsonValueKind.Array){
   throw new Exception("Must be an array");
}
jsonDocument.RootElement.EnumerateArray().Where("City ==\"Paris\"");

That would also allow us to use the extension method to use it inside of a JSON document.

@paule96
Copy link
Author

paule96 commented Apr 8, 2024

Hm I'm also not sure if the extension of Where is the correct idea. If I understand it correctly that would mean that we need to reimplement the ExpressionParser for it. Wouldn't it be better to allow, that the currently private methods of the ExpressionParser can be overwritten? In this case the ParseMemberAccess method. Then we could create kinda easy second project and make a special implementation of ParseMemberAccess for JsonElement.

But maybe I don't understand the project structure well enough jet.

@StefH
Copy link
Collaborator

StefH commented Apr 8, 2024

#791 WIP...

@paule96
Copy link
Author

paule96 commented Apr 9, 2024

Looks quite good. Incredible how fast you implemented that 😯
So you decided to create DynamicTypes out of each element in the JSONArray and then query on it.
I guess because it's the easiest way todo right now. Nice to see.

@StefH
Copy link
Collaborator

StefH commented Apr 9, 2024

I'm adding all methods and also working on System.Text.Json implementation. Can you take a look at the PR (WIP)?

@paule96
Copy link
Author

paule96 commented Apr 10, 2024

Yes I will review today :)

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

No branches or pull requests

2 participants