Skip to content

JSON path syntax for arrays within a GFF

ProlericProleric Member Posts: 1,316
I've successfully loaded a UTC into a JSON and can edit top-level fields.

Does anyone know the syntax for a path into an array within the GFF structure?

The comments in nw_inc_gff led me to try the third line below:
      json   jTemplate = TemplateToJson(sTemplate, RESTYPE_UTC);
      jTemplate = GffReplaceByte  (jTemplate, "Gender",          nGender);
      jTemplate = GffReplaceResRef(jTemplate, "Equip_ItemList/0/EquippedRes", sDress);

However, that line fails:

[Fri Oct 8 15:53:14] [json.exception.other_error.501] unsuccessful: {"op":"test","path":"/Equip_ItemList/0/EquippedRes/type","value":"resref"}
Error while deserializing object: [json.exception.type_error.305] cannot use operator[] with a string argument with null

Comments

  • ForSeriousForSerious Member Posts: 466
    Looks like there's a parse type mismatch. C needs types and the internal JSON to C parser is assigning it some type that cannot be accessed by []. Are you sure that Equip_ItemList is the exact name?
  • ProlericProleric Member Posts: 1,316
    I've checked the names, and ensured the field already exists, using GFF editor.

    I'm pretty sure what's wrong is the path syntax - the documentation says the leading / should be omitted but doesn't give an explicit example of an array. [0] doesn't work, either.
  • ForSeriousForSerious Member Posts: 466
    The example they give is: "/foo/0" "bar"
    Maybe you cannot do it in one line. Something like:
    	json   jTemplate = TemplateToJson(sTemplate, RESTYPE_UTC);
    	jTemplate = GffReplaceByte  (jTemplate, "Gender",          nGender);
    	json jTemp = JsonPointer(jTemplate, "Equip_ItemList/0");
    	jTemp = GffReplaceResRef(jTemp, "/EquippedRes", sDress);
    	jTemplate = GffReplaceStruct(jTemplate, "Equip_ItemList/0", jTemp);
    
    Sorry that code probably doesn't work, but is going the tedious direction I would try.
  • ProlericProleric Member Posts: 1,316
    With the slight correction of adding a leading / which JsonPointer requires,
    json jTemp = JsonPointer(jTemplate, "/Equip_ItemList/0");
    
    gives an error "value not found".

    I also tried 1 instead of 0, same error.
  • DazDaz Member Posts: 127
    edited October 2021
    If you dump the json of the UTC you'll see actual listarray is under the "value" object
        "Equip_ItemList": {
            "type": "list",
            "value": [
                {
                    "EquippedRes": {
                        "type": "resref",
                        "value": "nw_wblml001"
                    },
                    "__struct_id": 16
                },
                {
                    "EquippedRes": {
                        "type": "resref",
                        "value": "nw_it_creitem055"
                    },
                    "__struct_id": 131072
                }
            ]
        },
    

    So in order to replace the resref of the first item you need to do something like this:
    GffReplaceResRef(jUTC, "Equip_ItemList/value/0/EquippedRes", "myresref");
    
  • ProlericProleric Member Posts: 1,316
    Daz wrote: »
    So in order to replace the resref of the first item you need to do something like this:
    GffReplaceResRef(jUTC, "Equip_ItemList/value/0/EquippedRes", "myresref");
    

    That works! Thanks!

    Counter-intuitive, though. The quickest and most obvious way to discover the key names is to use a GFF editor. However, the keyword "value" isn't in the GFF itself, being inserted by TemplateToJson() to comply with the Json standard.

    Hopefully, there is a general rule that every array in a GFF requires a path element value/# to access element number # in the Json?
  • DazDaz Member Posts: 127
    Every list should work the same, yes. It's just how the gff->json conversion is implemented. If you look at a dumped template you'll notice every variable consists of a "type" and "value" object. The helper functions just hide them, there's just no helper functions to directly work on lists.
  • ProlericProleric Member Posts: 1,316
    I see that an alternative is to use GffGetList to process arrays within a GFF.

    Here's an example, examining the item properties of a UTI.

    Not sure that it's much clearer - notice that the keyword "value" still has to be inserted - taking your point that there's no direct helper function.
    // Determine whether clothing is rich, poor or neutal
    
    int zDressStatus(string sDress)
    {
      int    CLOTHING_NEUTRAL = 0;
      int    nProperty;
      json   jItem            = TemplateToJson(sDress, RESTYPE_UTI);
      json   jProperties      = GffGetList(jItem, "PropertiesList");
      int    n     = -1;
      json   jProperty        = JsonArrayGet(jProperties, ++n);
    
      while (JsonGetType(jProperty) != JSON_TYPE_NULL)
        {
          nProperty = JsonGetInt(JsonObjectGet(JsonObjectGet(jProperty, "PropertyName"), "value"));
    
          if ((nProperty == ITEM_PROPERTY_CLOTHING_POOR) || (nProperty == ITEM_PROPERTY_CLOTHING_RICH)) return nProperty;
    
          jProperty = JsonArrayGet(jProperties, ++n);
        }
    
      return CLOTHING_NEUTRAL;
    }
    
Sign In or Register to comment.