C# Nested JSON KeyName Duplication - c#

I searched first, and basically I am trying to avoid having to use JObject in C# in favor of ANY Serializer. An excerpt of a large Microsoft Dynamics JSON trace has JSON formed like this
{
"InBlockOStuff" :
{
"type":"Yea You Know What this is",
"values":[
{
"Key":"Target",
"Value":{
"type":"Yea You Know What this is",
"LogicalName":"Thangie",
"Id":"GuidAs String",
"MagicalContent":{
"type":"Yea You Know What this is",
"values":[
{
"Key":"firstname",
"Value":"New Test thangie One"
},
{
"Key":"Thangieid",
"Value":"some stupid Guid like thangie"
}
]
},
"Shaggy":null,
"SubCategory":{
"type":"Yea You Know What this is",
"values":[ ]
},
"Velma":{
"type":"Yea You Know What this is",
"values":[ ]
},
"Scoobie":null,
"KeyAttributes":{
"type":"Yea You Know What this is",
"values":[ ]
}
}
},
{
"Key":"some text",
"Value":true
},
{
"Key":"some text",
"Value":0
}
]
}
}
Notice the repeated instances of the "keys" value and values It is valid Json, the online validators say it is legit, the online generators will additionally create C# classes/objects but I'm sure you instantly see this mess will have two distinctly different "Values" classes. And that doesn't serialize cleanly.
So am I stuck having to learn JObject to get my data out of this mess?
This is just high level excerpt there exists, for example another MagicalContent key with a different set of key values inside of it, just for arguments sake.

Related

How to search in dynamodb with a complex value using .net sdk

I have just started with DynamoDB. I have background in MongoDB and relational databases and I am structuring my JSON in more like a graph structure than a flat structure. For example,
[
{
"id": "1",
"title": "Castle on the hill",
"lyrics": "when i was six years old I broke my leg",
"artists": [
{
"name": "Ed Sheeran",
"sex": "male"
}
]
}
]
For example, If I like to search the item by 'Ed Sheeran'. The closest I have got is this and this is not even matching any value.
var request = new ScanRequest
{
TableName = "Table",
ProjectionExpression = "Id, Title, Artists",
ExpressionAttributeValues = new Dictionary<string,AttributeValue>
{
{ ":artist", new AttributeValue { M = new Dictionary<string, AttributeValue>
{
{ "Name", new AttributeValue { S = "Ed Sheeran" }}
}
}
}
},
ExpressionAttributeNames = new Dictionary<string, string>
{
{ "#artist", "Artists" },
},
FilterExpression = "#artist = :artist",
};
var result = await client.ScanAsync(request);
Most of the example and tuturials I have watched so far, they have treated dynamodb as a table in a normal relational database with very flat design. Am I doing it wrong to structure the JSON as above? Should Artists be in a separate table?
And If it can be done, how do i search by some value in a complex type like in the above example?
First of all, you should not be using the scan operation in dynamodb. I would strongly recommend to use query. Have a look at this stack overflow question first.
If you want to search on any attribute, you can either mark them as the primary key (either hash_key or hash_key + sort_key) or create an index on the field you want to query on.
Depending on the use case of id attribute in your schema, if you are never querying on id attribute, I would recommend the structure something like this :
[
{
"artist_name" : "Ed Sheeran" // Hash Key
"id": "1", // Sort Key (Assuming id is unique and combination of HK+SK is unique)
"title": "Castle on the hill",
"lyrics": "when i was six years old I broke my leg",
"artists": [
{
"name": "Ed Sheeran",
"sex": "male"
}
]
}
]
Alternatively, if you also need to query on id and it has to be the hash key, you can an index on the artist_name attribute and then query it.
[
{
"artist_name" : "Ed Sheeran" // GSI Hash key
"id": "1", // Table Hash key
"title": "Castle on the hill",
"lyrics": "when i was six years old I broke my leg",
"artists": [
{
"name": "Ed Sheeran",
"sex": "male"
}
]
}
]
In either case, it is not possible to query inside a nested object without using scan operation and then iterating it in code, something which you have already tried.

Extract schema from JSON data in C#

I have below JSON schema which works ok with JsonConvert.DeserializeObject. I am able to extract schema directly from it but when it comes to JSON Data string, then I am not sure how to extract schema.
{
"fields": [
{
"name": "approved",
"type": "Boolean",
"displayName": "Approved",
"isNullable": true,
"isSearchable": false,
"isFilter": true,
"isInternal": false
}
]
}
In the above JSON, approved is the field name so I am able to extract schema, but I have a JSON data string as below and want to extract schema from it.
{
"skuId": "1",
"balance": [
{
"warehouseId": "1_1",
"warehouseName": "Main Warehouse",
"totalQuantity": 1000001,
"reservedQuantity": 1,
"hasUnlimitedQuantity": true,
"timeToRefill": null,
"dateOfSupplyUtc": null
}
]
}
In the above example JSON data, warehouseid, warehousename, etc., are fieldname and I need to have those in my schema in c#.
Can anyone please suggest?
create a new class, copy your json data string, and in visual studio click edit -> paste special, and it will create classes that you can deserialize to the way you want.
You are missing the closing ']' so that needs to be addressed first.
If you use a dictionary and need to iterate it :
foreach(KeyValuePair<string, string> entry in myDictionary) { // do something with entry.Value or entry.Key }

Can I represent my .NET dictionaries as JSON dictionaries in my GraphQL?

When I'm serialising to JSON, I'm used to .NET dictionaries becoming objects with the keys as properties and the values as their values. (The Json.Net docs have a succinct example.)
I'm using GraphQL and struggling to achieve a similar result. My data for this root query is basically a Dictionary<MyEnum,Dictionary<string,string>>. The closest I've got so far is this:
{
"data": {
"outterDict": [
{
"key": "THING_1",
"innerDict": [
{
"key": "key1",
"val": "val1"
},
...
]
},
{
"key": "THING_2",
"innerDict": [
{
"key": "key2",
"val": "val2"
},
...
]
}
]
}
}
But I want it to be closer to this:
{
"data": {
"collection": {
"THING_1": {
"key1": "val1",
...
},
"THING_2": {
"key2": "val2",
...
}
}
}
}
I'm struggling because GraphQL .Net only seems to understand lists, not dictionaries.
It doesn't feel like what I'm trying to do is unreasonable. Letting keys be keys seems right and like the most useful way to share this data (e.g. as suggested by this answer).
Is there a way to do this in GraphQL? Is there a way to do this in GraphQL .Net?
After quite of lot of research, it seems like this isn't in the spec of GraphQL and is therefore unsupported in GraphQL.Net.
GraphQL expects all possible properties (i.e. keys in a map/dictionary) to be known in advance. This means we lose a lot of the value of passing a dictionary at run time.
So although the GraphQL JSON is more verbose than idiomatic JSON, it's like this deliberately.

Deserializing Some Odd JSON using C#

I have a JSON document coming from a vendor that looks like this:
{
"content": [{
"name": "Windows 8.1 x64",
"id": "Windows81x64",
"components": {
"Windows81x64": {
"propertyGroups": ["VirtualWindows81x64"],
"dependsOn": [],
"data": {
"provisioning_workflow": {
"fixed": {
"id": "WIMImageWorkflow",
"label": "WIMImageWorkflow"
}
},
"memory": {
"default": 2048,
"min": 2048,
"max": 16384
}
}
}
}
}]
}
Most of this document is fairly easy to deserialize into an object using the typical DataContractSerializer, however, there are a couple of keys/values that I am not sure what the "best practice" might be.
If you look at the "components" key the first key after that one is titled "Windows81x64". This key can change from document to document and it can be any value. It almost should be a 'Name' property of the collection but I can't control that. Furthermore, inside the 'Windows81x64' key there is another property called 'data'. According to the vendor the value of data is 'anonymous.' So, basically it can be anything.
Any ideas on the best way to deserialize this into a custom object when it comes to those parts of the document? Thank you.
You can deserialize dynamic ones as Dictionary<string, object>
Or if you know the value's type you can use Dictionary<string, ValueType> where the key of the dictionary would be the name (in your case Windows81x64)

Get entity by its parent entity's value in Elasticsearch

Imagine we have this simple entity in ES
user {
username: "ultrauser"
name: "Greg"
address: [
{ city: "London" }, {city: "Prague" }
]
}
I need a query, which will return me all addreses for user "ultrauser".
I'm using NEST and for now, I'm doing it the way I select user where username="ultrauser" and then read only the addresses field by myself. So the ES will return me whole user entity, which contain addresses too.
But is it possible for ES to make query like "Give me all addresses, which belongs to user 'ultrauser'"?
I need ES to return list of addresses entities, not user entity, containing addresses. It is simple when you go from root to leafs (get user.address.city), but how can I select from leafs to root easily?
Important is, we can not use parent-child or nested document features because of other reasons.
Thanks for all you ideas.
You should probably read this article: http://www.elasticsearch.org/blog/managing-relations-inside-elasticsearch/ You're trying to apply RDBMS concepts to elasticsearch and that is usually a bad idea. Really, even if you are storing objects, they are still stored flat in elasticsearch behind the scenes.
I think this query will get you to where you want to be though, if I'm understanding you correctly:
{
"query": {
"bool": {
"must": [
{
"term": {
"username": "some matched item"
}
},
{
"filtered": {
"filter": {
"exists": { "field" : "address" }
}
}
}
]
}
},
"fields": [
"address"
]
}
Does it matter if you extract the addresses or if you ask elasticsearch to do it for you? Sometimes you don't want to send all that data over the wire if not needed and that might be your reason.
This will still return something like this:
hits: [
{
_index: indexname
_type: typename
_id: id
_score: 1.4142135
fields: {
address: [
{someaddress_object}
]
}
}, ...
So you will still need to loop through the results anyway when you get them back, just the result size is smaller.

Categories