LUIS Add Utterance in code JSON POST failing - c#

Following this example:
https://learn.microsoft.com/en-us/azure/cognitive-services/luis/luis-quickstart-cs-add-utterance
I am trying to send an utterance to my LUIS App.
It keeps on failing with this response message:
{
"error": {
"code": "BadArgument",
"message": "Failed to parse example labeling objects. Parameter name: exampleLabelObjects"
}
}
My input body is:
{
"text": "hi, what can I help you with?",
"intentName": "Help",
"entityLabels": []
}
And according too the link if you send an utterance without any entity labels the above is correct.
The entityLabels field is required. If you don't want to label any
entities, provide an empty list as shown in the following example:
[
{
"text": "go to Seattle",
"intentName": "BookFlight",
"entityLabels": [
{
"entityName": "Location::LocationTo",
"startCharIndex": 6,
"endCharIndex": 12
}
]
},
{
"text": "book a flight",
"intentName": "BookFlight",
"entityLabels": []
}
]
The C# to build the object is as follows:
public class LUISUtterItem
{
public string utterances;
public string text;
public string intentName;
public List<exampleLabelObjects> entityLabels;
}
public class exampleLabelObjects
{
public string entityName;
public int startCharIndex;
public int endCharIndex;
}
I call it using:
LUISUtterItem itm = new LUISUtterItem();
//itm.utterances = materialArray[1];
itm.text = materialArray[1];
itm.intentName = materialArray[2];
itm.entityLabels = new List<exampleLabelObjects>();
I have also tried not including an "entityLabels" object, as well as a string list that just gets initiated with the same result.
Any help will be appreciated.

So it seems like all you have to include in the body is "[]" around it and it worked:
[{
"text": "hi, what can I help you with?",
"intentName": "Help",
"entityLabels": []
}]

I faced the same issue. Solved by sending the body as:
{
"text": "hi",
"intentName": "Greetings"
}
Don't put entityLabel if it is not needed.

Related

Reading json with a key in unity 3d

Iam making a dictionary game in unity 3d. And i have a json file about all the definitions and examples of all vocabulary.Each word has key is the word it self ( which i highlighted). how can i get the value of each word(key). I have created an oject for json.
for example: i have a word "a cappella" it give me back:
a cappella
1: adverb
definition :without musical accompaniment
example : they performed a cappella
2 :adjective
definition :sung without instrumental accompaniment
example : they sang an a cappella Mass.
many thanks
Here is the model I use for the JSON
public class VocabularyModel : MonoBehavior
{
public string Word { get; set; }
public string WordId {get; set; }
public Meaning[] Meanings { get; set; }
public Label[] Labels { get; set; }
}
json String
{
"a cappella": {
"word": "a cappella",
"wordset_id": "5feb6f679a",
"meanings": [
{
"id": "492099d426",
"def": "without musical accompaniment",
"example": "they performed a cappella",
"speech_part": "adverb"
},
{
"id": "0bf8d49e2e",
"def": "sung without instrumental accompaniment",
"example": "they sang an a cappella Mass",
"speech_part": "adjective"
}
]
},
"AD": {
"word": "AD",
"wordset_id": "76c6ebfae9",
"meanings": [
{
"id": "4c21c72afa",
"def": "in the Christian era",
"speech_part": "adverb",
"synonyms": [
"A.D.",
"anno Domini"
]
}
]
},
"A.D.": {
"word": "A.D.",
"wordset_id": "b7e9d406a0",
"meanings": [
{
"id": "a7482f3e30",
"def": "in the Christian era",
"speech_part": "adverb",
"synonyms": [
"AD"
]
}
]
}
}
Are you using a library or you wrote the code yourself?
In the second case, I'd suggest to use Json.NET from Newtonsoft.
You can deserialize the JSON to a JObject and then treat it as if it was a dictionary.
To do this, you can structure your JSON in the following way:
{
"a_cappella" : {
"word" : "a cappella",
"wordId" : "123",
"meanings" : {...},
"labels" : {...}
}
"building" : {
"word" : "building",
"wordId" : "124",
"meanings" : {...},
"labels" : {...}
}
}
Then you deserialize into a JObject and search what you need:
var json = // here is your json string
var dictionary = JsonConvert.DeserializeObject(json);
if (dictionary.ContainsKey("a_cappella")){
return dictionary["a_cappella"].ToObject<VocabularyModel>();
}

Adding multiple properties into nested JSON array

I've done a lot of searching at it appears there is no article for this specific case.
I have some JSON (Note that it is a JArray, and not a JObject)
[
{
"Name": "Name 1",
"Icon": "Icon 1",
"Samples": [
{
"Name": "Sample 1",
},
{
"Name": "Sample 2",
},
{
"Name": "Sample 3",
}
]
},
{
"Name": "Name 2",
"Icon": "Icon 2",
"Samples": [
{
"Name": "Sample 1",
},
{
"Name": "Sample 2",
},
{
"Name": "Sample 3",
}
]
},
{
"Name": "Name 3",
"Icon": "Icon 3",
"Samples": [
{
"Name": "Sample 1",
},
{
"Name": "Sample 2",
},
{
"Name": "Sample 3",
}
]
},
]
So this has 3 levels. The root, which contains the "SampleCategories". The "SampleCategories" which contains some items and a "Samples" list, and the "Samples" list which contains many objects.
So, what I'm essentially trying to do here is to add an object into the Samples list, inside a specific SampleCategory. So for example:
I want to add "Sample 4" to the Samples array in "Name 1" so it looks like this:
{
"Name": "Name 1",
"Icon": "Icon 1",
"Samples": [
{
"Name": "Sample 1",
},
{
"Name": "Sample 2",
},
{
"Name": "Sample 3",
},
{
"Name": "Sample 4",
}
]
},
I thought this would be fairly easy when I started out but it turns out there are lots of roadblocks that I can't seem to get my head around.
So I have two models for each level, "SampleCategory" for the top level that has the Name, Icon and Samples, which goes off to another model called "Samples[]"
So I'm afraid I'm at an embarrassing point in this process... Right at the start. I've de-serialised the json, and done some bits around finding my chosen SampleCategory, and created an object ready to add in, and that's as far as I've gotten...
var categories = JsonConvert.DeserializeObject<List<SampleCategory>>(json);
var applications = categories.Find(c => c.Name.Equals("Name 1"));
var sample = new Sample
{
Name = "Sample 4",
};
I don't appear to be able to find any way of adding a new 'sample' into the Samples list of a chosen SampleCategory. I even tried adding to the object path directly, the path of which I got using this:
JObject jo = jsonArray.Children<JObject>().FirstOrDefault(o => o["Name"] != null && o["Name"].ToString() == "Name 1");
But there doesn't appear to be a way to add to an array as I guess it's a static length?
What is best practice modifying JSON like this?
Documentation (https://www.newtonsoft.com/json/help/html/ModifyJson.htm) suggests there a few ways to do it when playing around with JObjects, but it doesn't suggest a way to do it with nested objects inside of JArrays.
Can anyone help or suggest some methods to do this? I'm sure it's probably simple, but I'm going through a loop trying to figure it out.
I guess your model looks something like this:
public class Sample
{
public string Name { get; set; }
}
public class SampleCategory
{
public string Name { get; set; }
public string Icon { get; set; }
public List<Sample> Samples { get; set; }
}
If you are not sure how a model must look like to match a given json string you can make use of a tool like json2csharp which will generate the model for you.
To be able to add a new sample to a specific category you can find the specific category using LINQ after deserializing it:
var categories = JsonConvert.DeserializeObject<List<SampleCategory>>(json);
var category = categories.FirstOrDefault(c => c.Name == "Name 1");
Now (if a category with the name exists) just add the new sample to the list:
if(category != null)
{
category.Samples.Add(new Sample{Name = "Sample 4"});
}
To serialize it back to json:
var json = JsonConvert.SerializeObject(categories);
Edit
If you cannot switch your model type for Samples to List<T> and you don't want to convert the array temporarily to List<T>, you can do something like this:
if(category != null)
{
category.Samples = category.Samples.Concat(new Sample[]{new Sample{Name = "Sample 4"}}).ToArray();
}
If you are not bothered by an additional List<T> cast another approach would be:
if(category != null)
{
var tmpList = category.Samples.ToList();
tmpList.Add(new Sample{Name = "Sample 4"});
category.Samples = tmpList.ToArray();
}
I'm not sure but it could be as simple as :
applications.Samples.ToList().Add(sample);
I have no privilege to comment it :(

JSON Get List of attributes values

I have the following JSON, and I want to take a list of IDs with its values
For example in LINQ something like this: result.Select(x=>x.id)
I tried this:
var inner = outer["pictures"].Value<JArray>().ToList();
I have a list there but with all attributes but I am not able to select just IDs since it is an anonymous list.
outer
{{
"id": "669654603",
"pictures": [
{
"id": "659745-MLA25600661898_052017",
"url": "http://mla-s2-p.mlstatic.com/659745-MLA25600661898_052017-O.jpg",
"secure_url": "https://mla-s2-p.mlstatic.com/659745-MLA25600661898_052017-O.jpg",
"size": "500x365",
"max_size": "625x457",
"quality": ""
},
{
"id": "908422-MLA25658267858_062017",
"url": "http://mla-s2-p.mlstatic.com/908422-MLA25658267858_062017-O.jpg",
"secure_url": "https://mla-s2-p.mlstatic.com/908422-MLA25658267858_062017-O.jpg",
"size": "47x47",
"max_size": "47x47",
"quality": ""
},
{
"id": "794138-MLA25658267889_062017",
"url": "http://mla-s2-p.mlstatic.com/794138-MLA25658267889_062017-O.jpg",
"secure_url": "https://mla-s2-p.mlstatic.com/794138-MLA25658267889_062017-O.jpg",
"size": "40x40",
"max_size": "40x40",
"quality": ""
}
]
}}
When working with Newtonsoft JSON you can do it like this:
var values = JObject.Parse(jsonString)["pictures"].Select(p => p["id"].Value<string>()).ToList();
In order to be valid your json should not contain double curly brackets:
{
"id": "669654603",
"pictures": [ ... ]
}
You can parse it without additional classes:
var ids = JObject.Parse(json)["pictures"].Select(p => (string)p["id"]);
Output:
[
"659745-MLA25600661898_052017",
"908422-MLA25658267858_062017",
"794138-MLA25658267889_062017"
]
Or you can create several classes to hold your json data:
public class Container
{
public List<Picture> Pictures { get; set; }
}
public class Picture
{
public string Id { get; set; }
// you can add other properties here
}
And use strongly-typed parsing:
var ids = JsonConvert.DeserializeObject<Container>(json).Pictures.Select(p => p.Id);

Search for a nested value inside of a JSON.net object in C#

I've got a JSON stream coming back from a server, and I need to search for a specific value of the node "ID" using JSON.net to parse the data.
And I can almost make it work, but not quite because the results coming back are deeply nested in each other -- this is due to the fact that I'm getting a folder structure back. I've boiled the JSON down to a much simpler version. I'm getting this:
{
"data": {
"id": 0,
"name": "",
"childFolders": [{
"id": 19002,
"name": "Locker",
"childFolders": [{
"id": 19003,
"name": "Folder1",
"childFolders": [],
"childComponents": [{
"id": 19005,
"name": "route1",
"state": "STOPPED",
"type": "ROUTE"
}]
}, {
"id": 19004,
"name": "Folder2",
"childFolders": [],
"childComponents": [{
"id": 19008,
"name": "comm1",
"state": "STOPPED",
"type": "COMMUNICATION_POINT"
}, {
"id": 19006,
"name": "route2",
"state": "STOPPED",
"type": "ROUTE"
}, {
"id": 19007,
"name": "route3",
"state": "STOPPED",
"type": "ROUTE"
}]
}],
"childComponents": []
}],
"childComponents": []
},
"error": null
}
I can almost get there by going:
var objects = JObject.Parse(results);
var subobjects = objects["data"]["childFolders"][0]["childFolders"][1];
I can see in the debug view that it'll parse the object, but won't let me search within.
My ultimate goal is to be able to search for "route3" and get back 19007, since that's the ID for that route. I've found some results, but all of them assume you know how far nested the object is. The object I'm searching for could be 2 deep or 20 deep.
My ultimate goal is to be able to search for "route3" and get back 19007
You can use linq and Descendants method of JObject to do it:
var dirs = JObject.Parse(json)
.Descendants()
.Where(x=>x is JObject)
.Where(x=>x["id"]!=null && x["name"]!=null)
.Select(x =>new { ID= (int)x["id"], Name = (string)x["name"] })
.ToList();
var id = dirs.Find(x => x.Name == "route3").ID;
You can use the SelectToken or SelectTokens functions to provide a JPath to search for your desired node. Here is an example that would provide you the route based on name:
JObject.Parse(jsonData)["data"].SelectToken("$..childComponents[?(#.name=='route3')]")
You can find more documentation on JPath here
Simply write a recursive function:
private Thing FindThing(Thing thing, string name)
{
if (thing.name == name)
return thing;
foreach (var subThing in thing.childFolders.Concat(thing.childComponents))
{
var foundSub = FindThing(subThing, name);
if (foundSub != null)
return foundSub;
}
return null;
}
class RootObject
{
public Thing data { get; set; }
}
class Thing
{
public int id { get; set; }
public string name { get; set; }
public List<Thing> childFolders { get; set; } = new List<Thing>();
public List<Thing> childComponents { get; set; } = new List<Thing>();
}
And using it:
var obj = JsonConvert.DeserializeObject<RootObject>(jsonString);
var result = FindThing(obj.data, "route3");

How to create set of Multiple JSON with same header

I have a JSON that has the following pattern to be created before
hitting the API, See below
"recipientSetInfos":
[
{
"recipientSetMemberInfos":
[
{
"fax": "",
"email": ""
}
],
"recipientSetRole":
{
"SIGNER": "enum",
"APPROVER": "enum"
},
"signingOrder": 0
}
]
Using this predefined Format, i want to create Multiple signer set's,
like the below.
"recipientSetInfos":
[
{
"recipientSetMemberInfos":
[{
"email": "def#gmail.com"
}],
"recipientSetRole": "SIGNER"
}, {
"recipientSetMemberInfos": [{
"email": "abc#gmail.com"
}],
"recipientSetRole": "SIGNER"
}],
I am using C# Programming Language, if i just hard code it & send. It
works but if i want to create dynamically. How can i achieve this.
Currently I am using this like
RecipientSetInfo rec_Info = new RecipientSetInfo();
rec_Info.recipientSetMemberInfos = List_Emails;
rec_Info.recipientSetRole = "SIGNER";
List_Recipients.Add(rec_Info);
which gives an output of :
{
"recipientSetMemberInfos":
[
{"email":"abc#ae.com"},
{"email":"def#gmail.com"},
{"email":"fgh#gmail.com"}
],
"recipientSetRole":"SIGNER"
}
But using this logic, i am not getting the desired output. It is
considering all 3 emails as one.
Just to add, one more thing with the help of one user, i tried to code out this
foreach (var email in List_Emails)
{
var rec_Info = new RecipientSetInfo();
rec_Info.recipientSetRole = "SIGNER";
List_Recipients.Add(rec_Info);
}
But problem still exists, since "recipientSetInfos" has two subdivisions i.e. recipientSetRole & recipientSetMemberInfos within which "recipientSetMemberInfos" has one attribute Email.
So when i add the two lists together it comes out Email to be Null
"recipientSetInfos":
[
{"recipientSetMemberInfos":null,
"recipientSetRole":"SIGNER"
‌​},
{"recipientSetMemberInfos":null,
"recipientSetRole":"SIGNER"
}
]
Structure for both the elements i have created like -
public class RecipientSetMemberInfo
{
public string email { get; set; }
}
public class RecipientSetInfo
{
public List<RecipientSetMemberInfo> recipientSetMemberInfos { get; set; }
public string recipientSetRole { get; set; }
}
Please suggest ??
Your problem is that you create one RecipientSetInfo instead of one for each email.
The following will loop through List_Emails collection and will add them to the list List_Recipients.
foreach (var email in List_Emails)
{
var rec_Info = new RecipientSetInfo();
rec_Info.recipientSetRole = "SIGNER";
List_Recipients.Add(rec_Info);
}

Categories

Resources