I can not google that thing on json.net api reference or anywhere.
I want to create object from json schema with default values filled in.
Basically some thing like this:
var JsonSchema=JsonSchema.ReadSchemaFromSomeWhere();
dynamic DefaultObject= JsonSchema.GetDefaultObject();
Example you might see in json-schema-defaults package.
Example
var JsonSchema=JsonSchema.ReadSchemaFromString("
{
"title": "Album Options",
"type": "object",
"properties": {
"sort": {
"type": "string",
"default": "id"
},
"per_page": {
"default": 30,
"type": "integer"
}
}");
dynamic DefaultObject= JsonSchema.GetDefaultObject();
//DefaultObject dump is
{
sort: 'id',
per_page: 30
}
UPDATE
I want lib or api in json.net to create object with default values from any given valid json schema during runtime.
Well a simple case might be this
[Test]
public void Test()
{
dynamic ob = new JsonObject();
ob["test"] = 3;
Assert.That(ob.test, Is.EqualTo(3));
}
I used the RestSharp library that provides a good dynamic implementation that allows indexing ["test"];
So then - what You're left to do is read the properties from the schema and assign values (of course this will work only for simple plain case`s, but might be a start
dynamic ob = new JsonObject();
foreach (var prop in JsonSchema.Properties)
{
if (prop.Default != null)
ob[prop.Name] = prop.Default
}
Related
I have JSON file in Azure Storage which I am reading using C#. In that JSON file there is anode called SQLViewDifinition and that node I have SQL which I need to fetch.
I have read the file into a string and converted that string in JObject. I have the JSON now but is finding it difficult to read that particular node. Tried with JToken and Jproperty. But could not crack it.
JSON file looks like this:
{
"jsonSchemaSemanticVersion": "1.4.0",
"imports": [
{
"corpusPath": "cdm:/foundations.cdm.json"
},
{
"corpusPath": "localCdm:/foundations.cdm.json"
}
],
"definitions": [
{
"entityName": "METCredManCollectionGroupEntity",
"exhibitsTraits": [
{
"traitReference": "is.CDM.entityVersion",
"arguments": [
{
"name": "versionNumber",
"value": "1.0.0"
}
]
},
{
"traitReference": "has.sqlViewDefinition",
"arguments": [
{
"name": "sqlViewDefinition",
"value": "CREATE VIEW [DBO].[METCREDMANCOLLECTIONGROUPENTITY] AS SELECT T1.COLLECTIONGROUPID AS COLLECTIONGROUPID, T1.DESCRIPTION AS DESCRIPTION, T1.RECID AS CREDMANCOLLECTIONGROUPTABLERECID, T1.DATAAREAID AS CREDMANCOLLECTIONGROUPTABLEDATAAREAID, T1.RECVERSION AS RECVERSION, T1.PARTITION AS PARTITION, T1.RECID AS RECID FROM CREDMANCOLLECTIONGROUPTABLE T1"
}
]
},
{
"traitReference": "has.backingElements",
"arguments": [
{
"name": "backingElements",
"value": "CredManCollectionGroupTable"
}
]
}
],
"hasAttributes": [
{
"name": "CollectionGroupId",
"dataType": "CredManCollectionGroupId",
"isNullable": true,
"displayName": "Collection group",
"maximumLength": 10
},
{
"name": "Description",
"dataType": "Description",
"isNullable": true,
"displayName": "Description",
"maximumLength": 60
},
{
"name": "CredmanCollectionGroupTableRecId",
"dataType": "other",
"isNullable": true,
"displayName": "Record-ID"
},
{
"name": "CredmanCollectionGroupTableDataAreaId",
"dataType": "other",
"isNullable": true,
"displayName": "Company"
}
],
"displayName": "MET Collection groups (Shared)"
},
{
"explanation": "Collection group",
"dataTypeName": "CredManCollectionGroupId",
"extendsDataType": "SysGroup"
},
{
"explanation": "Group",
"dataTypeName": "SysGroup",
"extendsDataType": "string"
},
{
"explanation": "Description",
"dataTypeName": "Description",
"extendsDataType": "string"
}
]
}
I need to find sqlViewDefinition from this file.
So far I can read the JSON in a JSON object. But could not find a way to get the view definition.
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
using Nancy.Json;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public class FindFiles
{
// Main Method with int return type
static int Main(String[] args)
{
Console.WriteLine("Buid SQL");
// for successful execution of code
return X("FILE_NAME");
}
public static int X(string fileName)
{
//connection string
string storageAccount_connectionString = "CONNECTION_STRING";
// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(storageAccount_connectionString);
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve reference to a previously created container.
CloudBlobContainer container = blobClient.GetContainerReference("CONTAINER");
//The specified container does not exist
try
{
//root directory
CloudBlobDirectory dira = container.GetDirectoryReference(string.Empty);
//true for all sub directories else false
var rootDirFolders = dira.ListBlobsSegmentedAsync(true, BlobListingDetails.Metadata, null, null, null, null).Result;
foreach (var blob in rootDirFolders.Results)
{
if (blob.Uri.OriginalString.Contains(fileName, StringComparison.OrdinalIgnoreCase) && blob.Uri.OriginalString.Contains(".cdm.json", StringComparison.OrdinalIgnoreCase))
{
Console.WriteLine("Blob: " + blob.Uri.OriginalString);
if (blob.GetType() == typeof(CloudBlockBlob))
{
CloudBlockBlob b = (CloudBlockBlob)blob;
string jsonText = b.DownloadTextAsync().Result;
Dictionary<string, object> json_Dictionary = (new JavaScriptSerializer()).Deserialize<Dictionary<string, object>>(jsonText.ToString());
JObject json = JObject.Parse(jsonText);
}
}
}
}
catch (Exception e)
{
// Block of code to handle errors
Console.WriteLine("Error", e);
}
return 1;
}
}
As you are using .NET 6 and because the structure is always the same, the easiest way to deserialize is to mimic the structure of the JSON in C# classes. You can then easily deserialize the JSON into objects and access the properties of the objects instead of "brachiating" through dynamic data.
In order to get the classes, you can use Visual Studio's Paste Special function (Edit -> Paste special -> Paste JSON as classes). This generates the classes for you (you can adjust the classes if you don't need parts of them or change the casing of the property names; also you can use attributes to customize the serialization).
Afterwards, it is easy to parse the JSON into an object, e.g. (I've put your sample JSON into the jsonContent variable):
var obj = System.Text.Json.JsonSerializer.Deserialize<Rootobject>(jsonContent);
Because it still is a complex structure, getting to the SQL needs a bit of code:
Console.WriteLine(obj
.definitions[0]
.exhibitsTraits
.Where(x => x.traitReference == "has.sqlViewDefinition")
.First().arguments.Where(x => x.name == "sqlViewDefinition")
.First().value);
Finally, the above code writes the following output:
CREATE VIEW [DBO].[METCREDMANCOLLECTIONGROUPENTITY] AS SELECT T1.COLLECTIONGROUPID AS COLLECTIONGROUPID, T1.DESCRIPTION AS DESCRIPTION, T1.RECID AS CREDMANCOLLECTIONGROUPTABLERECID, T1.DATAAREAID AS CREDMANCOLLECTIONGROUPTABLEDATAAREAID, T1.RECVERSION AS RECVERSION, T1.PARTITION AS PARTITION, T1.RECID AS RECID FROM CREDMANCOLLECTIONGROUPTABLE T1
You can use this documentation to get familiar with JSON handling in .NET 6.
I am using Avro schema to dynamically produce message to a Kafka cluster from a C# application, using the Confluent Kafka client. The data types are not known on compile time so I am using the GenericRecord class from the Avro.Generic namespace, as described here: https://www.confluent.io/blog/decoupling-systems-with-apache-kafka-schema-registry-and-avro/.
I however have an issue - if the schema has a field that can contain null value, it is still required to add the field to the GenericRecord by using the Add method, giving null as value. My application is not aware of the fields that can be null and I don't think it should be - because that would defy the purpose of nullable fields in the schema.
Avro schema:
{
"namespace": "Test",
"type": "record",
"doc": "Test bool type",
"name": "BoolType",
"version": "1",
"fields": [
{
"name": "Data",
"type": [ "null", "boolean" ],
"default": null
},
{
"name": "Source",
"type": "string"
}
]
}
C# code:
var valueRecord = new GenericRecord( valueAvroSchema );
valueRecord.Add( "Data", null );
valueRecord.Add( "Source", "Test app .NET" );
var messageToSend = new Message<GenericRecord, GenericRecord>
{
Key = keyRecord,
Value = valueRecord
};
await _producer.ProduceAsync( _topicName, messageToSend );
If the line:
valueRecord.Add( "Data", null );
is not present, the ProduceAsync method throws a Confluent.Kafka.ProduceException, as seen in the screenshot below.
Is there any way I can automatically populate the fields that can be null in the GenericRecord? The same would apply if I would have to populate the fields with their default value.
Is there any way of doing this in a standard way or do I need to write my own code to read the schema and if there are any nullable fields that are not already set by my application to add them at the end, before publishing?
Thank you!
Avro defaults are only relevant to consumers. The producer must always set each field
I'm using the Fhir-net-api with DSTU2 to parse JSON objects to C# models. Everything works well, except that I can't access the Reason element of the resource type Procedure. As an example, I parse following JSON object to the Procedure model using the FhirParser:
{
"resourceType": "Procedure",
"identifier": [
{
"system": "https://mrd2.melanoma.org.au/fhir",
"value": "100200199664802"
}
],
"subject": { "reference": "Patient/10101000001733" },
"status": "completed",
"category": {
"coding": [
{
"system": "https://mrd2.melanoma.org.au/fhir/RootType",
"code": "3004"
}
],
"text": "Primary Surgery"
},
"bodySite": [
{
"coding": [
{
"system": "http://snomed.info/sct",
"code": "7771000"
}
],
"text": "Left Forearm, Anterior"
}
],
"reasonReference": { "reference": "/Condition/10106000001807" },
"performedDateTime": "1968-03-11",
"report": [ { "reference": "/DiagnosticReport/100200199664828" } ]
}
and the generated object has following entries (excerpt):
Procedure
I can access Report[0].Reference just fine but it won't work with Reason.Reference. Is the data in my JSON object wrong?
I've seen that Reason is of type Hl7.Fhir.Model.Element and Report of type Hl7.Fhir.Model.ResourceReference. Is there a way to change Reason to Hl7.Fhir.Model.ResourceReference and then access the Reference element?
Would be grateful for any hints. Thanks.
Regards,
Trammy
As you noticed, the type of reasonReference is Model.Element, while the type of report is ResourceReference. This difference has its origin in the definition of these elements in the FHIR specification for Procedure, where report is fixed to the type Reference but reason (or rather reason[x]) can either be a CodeableConcept or a Reference.
When elements can be of multiple types (we call this a "choice element", and you can recognize them because their name ends with [x] in the specification), we have created a C# member that is of type Model.Element (the base class for both Reference and CodeableConcept).
Now, depending on the instance you have just parsed or received, the contents of the reason member can be one of both types. So, you'll have to check in your code:
if(Reports[0].reason is ResourceReference)
{
var reference = (ResourceReference)Reports[0].reason;
//handle the case where this is a reference
//doing reference.Reference will now work as expected
}
else if(Reports[0].reason is CodeableConcept)
{
var concept = (CodeableConcept)Reports[0].reason;
//handle the case where this is a codeable concept
}
else
{
// Oops! Should not happen unless the standard has changed
}
Of course, if you are sure you can only receive instances where reason is a ResourceReference, you can do a cast directly:
var myReference = (ResourceReference)Reports[0].Reference;
// myReference.Reference and myReference.Display will now work
Using C# and Visual Studio 2010 (Windows Form Project), InstaSharp and Newtonsoft.Json libraries.
I want to get the image url from the JSON string returned to me by the Endpoint Instagram API when I request for a particular hashtag.
I can so far retrive the JSON string.
I am trying to use Newtonsoft.Json to deserialize the object using the examples, but I probably dont understand the JSON string representation of the object properly.
Below is a simplified sample response I get from the api call tags/tag-name/media/recent from their documentation. source here
{
"data": [{
"type": "image",
"filter": "Earlybird",
"tags": ["snow"],
"comments": {
}
"caption": {
},
"likes": {
},
"created_time": "1296703536",
"images": {
"low_resolution": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/02/f9443f3443484c40b4792fa7c76214d5_6.jpg",
"width": 306,
"height": 306
},
"thumbnail": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/02/f9443f3443484c40b4792fa7c76214d5_5.jpg",
"width": 150,
"height": 150
},
"standard_resolution": {
"url": "http://distillery.s3.amazonaws.com/media/2011/02/02/f9443f3443484c40b4792fa7c76214d5_7.jpg",
"width": 612,
"height": 612
}
},
"id": "22699663",
"location": null
},
...
]
}
I want to get specifically the standard_resolution in the images part.
This is the revelevant code that I currently have.
//Create the Client Configuration object using Instasharp
var config = new InstaSharp.Endpoints.Tags.Unauthenticated(config);
//Get the recent pictures of a particular hashtag (tagName)
var pictures = config.Recent(tagName);
//Deserialize the object to get the "images" part
var pictureResultObject = JsonConvert.DeserializeObject<dynamic>(pictureResult.Json);
consoleTextBox.Text = pictureResult.Json;
var imageUrl = pictureResultObject.Data.Images;
Console.WriteLine(imageUrl);
I get the error: Additional information: Cannot perform runtime binding on a null reference
so imageUrl is indeed null when I debug, hence indicating I am not accessing it the right way.
Anyone can explain to me how to access different parts of this JSON String using Newtonsoft.Json?
Using Newtonsoft.Json
dynamic dyn = JsonConvert.DeserializeObject(json);
foreach (var data in dyn.data)
{
Console.WriteLine("{0} - {1}",
data.filter,
data.images.standard_resolution.url);
}
I wrote a plugin for .net which takes care of deserializing the json string and returning a data table. it is still in development but see if it helps. Instagram.NET on Github
I've tried multiple ways of doing this and can't seem to find the proper solution. The JSON I am trying to parse looks like this
{
"data":
{
"random1":
{
"language": "en",
"state": "fl"
},
"completelyrandom":
{
"language": "fr",
"state": "wa"
}
}
}
Currently I am using the below JSON.NET to deserialize into a dynamic object, which gives me access to "language", "state" but I don't know what the parent object is.
var jsonSerializer = new JsonSerializer();
dynamic value = jsonSerializer.Deserialize(new JsonTextReader(new StringReader(json)));
foreach (var obj in value.data)
{
var myObj = obj.First;
string language = myObj.language;
}
How do I get access to "random1" and "completelyrandom"
Yeah, writing all of it out cleared my head. obj.Name gives my the container.