Parse json using x++ without contract classes

Hi Martin,
As discussed creating a separate thread on yhis.
I need your help to parse the JSON to get the text value “Hello”
str jsonResponse = ‘[{“translations”:[{“text”:“hello”,“to”:“en”}]}]’;

“JsonArray jsonArray = JsonArray::Parse(jsonResponse);
JsonObject jsonObject = jsonArray.Get(0).Get(“translations”).Get(0);
translatedText = jsonObject.Get(“text”).GetString();”

Compile error :get(system.int) is not supported -

For reference, Pranav’s original thread is Translate table data form one language to another.

I’m assuming you’re talking about .NET classes defined in System.Text.Json.Nodes namespace. (Please include such information next time.)

I don’t see any Get() method in JsonArray documentation. Therefore I agree with the compiler - such a method simply doesn’t exist. Look into the documentation to see what methods and properties you can use.

In your case, use an enumerator. For example:

System.Collections.IEnumerator enumerator = jsonArray.GetEnumerator();
 
while (enumerator.MoveNext())
{
    JsonObject translations = enumerator.Current as JsonObject;
}
1 Like

Hi Martin,
I’m using the below code,
JsonNode jsonNode = JsonNode::Parse(jsonResponse);
JsonArray jsonArray = jsonNode.AsArray();
System.Collections.IEnumerator enumerator = jsonArray.GetEnumerator();
while (enumerator.MoveNext())
{
JsonObject translations = enumerator.Current as JsonObject;
translatedText = translations.GetValue(“text”).ToString();------>Error (getvalue(system.string) is not found on type 'system.text.json.nodes.jsonobject
}

Please use ``` block when sharing code. Making it difficult to read (and therefore for others to help you) isn’t in your interest.

Isn’t this much better?

JsonNode jsonNode = JsonNode::Parse(jsonResponse);
JsonArray jsonArray = jsonNode.AsArray();
System.Collections.IEnumerator enumerator = jsonArray.GetEnumerator();
while (enumerator.MoveNext())
{
    JsonObject translations = enumerator.Current as JsonObject;
    // ------>Error (getvalue(system.string) is not found on type 'system.text.json.nodes.jsonobject
    translatedText = translations.GetValue("text").ToString();
}

The error message is actually very clear - JsonObject class has no GetValue(String) method, therefore trying to call it must fail. You can’t just make up method names; you need to use methods that the class has. Again, you can look into documentation (JsonObject Class) to see what methods are available. You should be also able to see methods and their parameters directly in the Visual Studio (thanks to IntelliSense).

Thanks for the alignment, I will follow from next time.By the way I don’t get the exact method to get the value from the specific node. there are some limitations using x++. (I had tried using keyvaluepair & contains key method but still no luck.

There is GetValue<T>() method, but you can’t call generic methods from X++ (at least it didn’t work when I tried it a few years ago). You can use this method if you create a .NET library, do this stuff there and call your library (not exposing any generics) from X++. I do it every time when I have more than a few lines of .NET code, or whenever I need a feature that isn’t supported by X++. In your case, I would definitely do it. In your case, it’d also allow you to use the generic extension methods such as First().

But you can do it with X++ too, if you wish.

Before looking at code, let me point out to another bug in your code. What you have in translations variable is the first object of the outer-most array, which is this:

{
  "translations":
  [
    {
      "text": "hello",
      "to":"en"
    }
  ]
}

Therefore its property is called translations, not text. The object with text property is inside the array value of translations property.

There is TryGetPropertyValue() method that you could use. For example:

JsonNode transArray;
if (translations.TryGetPropertyValue("translations", byref transArray))
{
    ...
}

Alternatively, you could use GetAt(Int32), possibly with IndexOf(String).

Note that this code is complex not because it has to be, but because you’ve decided to use this particular approach. If you just let generate contract objects from JSON and deserialize JSON to these contract objects, you could have accessed values in easy, object-oriented way. You could have also utilized JSONPath to fetch the particular element you want.

Since I have one parameter, I thought to go with the simple approach rather than using contract classes. That’s fine I will use the contract class then. thanks for your input. I thought i almost got it near using the above code, because of one value I need to rework again, that’s my worry.

Don’t ignore JSONPath either. If you just want a single value, it may be the best approach. You’ll simply ask for the value you want; instead of getting all objects in the path, iterating arrays etc. (or generating contracts).

I think you should choose what’s the easiest to implement for you.

“Hello” keyword is the one I translated from Thai to English . I need that value to be returned. It’s always the text value .

without using contract classes, I cracked it .
JsonNode jsonNode = JsonNode::Parse(jsonResponse);
JsonArray jsonArray = jsonNode.AsArray();
System.Collections.IEnumerator enumerator = jsonArray.GetEnumerator();
while (enumerator.MoveNext())
{
JsonObject translations = enumerator.Current as JsonObject;
if (translations.TryGetPropertyValue(“translations”,byref jsonNode))
{
JsonArray translationarray = jsonNode as JsonArray;
JsonObject translationobject;
if (translationarray && translationarray.Count>0)
{
translationobject = translationarray.get_Item(0) as JsonObject;
if(translationobject && translationobject.TryGetPropertyValue(“text”,byref jsonNode))
{
translatedText = jsonNode.ToString();
}
}
}
}

Good to hear that.

Now you just to learn how to post code to this forum (as discussed before).

yes Martin . Thank you for helping me.