1
votes

I'm trying to get the context variables that I made in Watson Conversation Dialogs in my Unity project. I am able to get the whole JSON dialog to show up in Unity, get the intents, entities and output text from the json file. So instead of getting the output:{ text[] out of the json file, I'm trying to get the context:{ variable:value out of the JSON file but I can't get my head around how.

This is the JSON file for the welcome dialog node where i want to read the destination_city variable out of to set it equal to an Unity variable/string.

{
   "context": {
     "date": null,
     "time": null,
     "hotel": null,
     "DateEnd": null,
     "DateBegin": null,
     "PeriodDate": null,
     "numberKids": null,
     "roomsHotel": null,
     "PeriodNumber": null,
     "numberAdults": 0,
     "departure_city": null,
     "transportation": null,
     "destination_city": "London",
     "kidDiscountRepeat": null
   },
   "output": {
     "text": {
       "values": [
         "Hello, this is the Watson Travel agency."
       ],
       "selection_policy": "sequential"
     }
   }
 }

And this is part of the code I have in Unity to get a response from Watson conversation and show the whole JSON file for that dialog node:

void HandleMessageCallback (object resp, Dictionary customData) 
{ object _tempContext = null; (resp as Dictionary ).TryGetValue("context", out _tempContext);

     if (_tempContext != null)
         conversationContext = _tempContext as Dictionary<string, object>;

     Dictionary<string, object> dict = Json.Deserialize(customData["json"].ToString()) as Dictionary<string, object>;

     // load output --> text;answer from Json node
     Dictionary <string, object> output = dict["output"] as Dictionary<string, object>;
     List<object> text = output["text"] as List<object>;
     string answer = text[0].ToString();
     Debug.Log("WATSON | Conversation output: \n" + answer);

     //======== Load $ context variable attempts =============================
     Debug.Log("JSON INFO: " + customData["json"].ToString());
     //=====================================

     if (conversationOutputField != null)
     {
         conversationOutputField.text = answer;
     }
1
text[0] should be values, if you want what is inside, you should probably try text[0][0] which should give you "Hello, this is the Watson Travel agency.". You should also look into Foreach since you are making everything an ICollection, you won't have to hassle yourself with managing indices. Also, I never see conversationOutputField being initialized anywhere, what is it's value ? - Antry
Thank you for your help, but I already can acces and show the "Hello, this is the Watson Travel agency" part. What I'm trying to acces is the destination city: "London" part. - grunter-hokage
You already have dict you should be able to access if with var myCity = dict["context"]["destination_city"] as Dictionary<string, object>; - Antry
That doesn't work. I get the error: cannot apply indexing with [] to an expression of type 'object' - grunter-hokage
Oh i'm sorry I went too fast x) Yeah it's var context = dict["context"] as Dictionary<string, string> you should then be able to access it with context["destination_city"] - Antry

1 Answers

2
votes

Solution 1 : Keeping your code

Taking your current code, you should be able to access your context with

var context = dict["context"] as Dictionary<string, object>

Now that you have your context, you can access it's content in the same way

var mycity = context["destination_city"]

Conclusion 1

Even though this does work, if you are setting up a solution where you are going to manipulate/access Json, I highly advise making models of your data to serialize to and from, for this, check out Unity's JsonUtility (Json Serialization)

Solution 2 : Serialize C# Objects to and from Json

Let's take Unity's Manual example:

Data Model Class

First, we create a Model class of the Json information that we want, in this case, we want information about our player, for this we create 3 fields, int level, float timeElapsed and string playerName.

[Serializable]
public class MyClass
{
    public int level;
    public float timeElapsed;
    public string playerName;
}

Data initialization

Here we create a new Instance of our class MyClass called myObject and manually set it's fields values (in fact, how you set the values is not really important here)

MyClass myObject = new MyClass();
myObject.level = 1;
myObject.timeElapsed = 47.5f;
myObject.playerName = "Dr Charles Francis";

Serializing your class to Json

To serialize your myObject just pass it to JsonUtility's .ToJson method as parameter

string json = JsonUtility.ToJson(myObject);

Now, we have our class's object equivalent as a Json string:

{"level":1,"timeElapsed":47.5,"playerName":"Dr Charles Francis"}

Generating Json from your class

If you want to populate your C# Object with the data from your Json, you can do so by calling JsonUtility's .FromJson<TypeOfTheClassImMappingTo> Method and passing it the json string as parameter.

myObject = JsonUtility.FromJson<MyClass>(json);

These are only basic operations and the surface of what you could do with JsonUtility's Class/Json serialization

Conclusion 2

This solution is a lot more maintainable. You can extend it to use any number of model types, and have the advantage and ease of navigation of C# objects. This is particularly interesting to create systems which will use your Data Objects.

If you have questions about Json Utility, like how to manage arrays, nested data etc.. I highly advise taking a couple of minutes to read through @Programmers Answer about JsonUtility practices.

Ressources

[Unity - Manual] JsonUtility / JsonSerialization

[StackOverflow] Serialize and Deserialize Json and Json Array in Unity