Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert JSON/Dynamic Structure to Map in Haxe?

I'm a very new to coding and generally work with a drag and drop editor that is based on Haxe (Stencyl) as a hobby.

I have a JSON file that I would like to convert into a nested map (dictionary). I have tried using the JSON parsing function but it returns an anonymous (dynamic) structure.

How can I either convert the JSON file into a map or convert the Anonymous structure into a map?

Sample of the JSON:

{
  "apple": {
    "value": 10,
    "health": 15,
    "tags": [
      "fruit",
      "fiber",
      "sweet"
    ]
  },
  "lemon": {
    "value": 5,
    "health": 10,
    "tags": [
      "fruit",
      "citrus",
      "sour"
    ]
  },
  "ham": {
    "value": 50,
    "health": 50,
    "tags": [
      "salty",
      "meat"
    ]
  }
}
like image 798
Xinxei Avatar asked Aug 07 '18 01:08

Xinxei


3 Answers

Another option would be to use the json2object library, which natively supports Map<String, T>:

import sys.io.File;
import json2object.JsonParser;

class Main {
    public static function main() {
        var parser = new JsonParser<Data>();
        var source = File.getContent("data.json");
        var data = parser.fromJson(source, "data.json");
        trace(data["apple"].value); // 10
    }
}

typedef Data = Map<String, {
    var value:Int;
    var health:Int;
    var tags:Array<String>;
}>

This approach avoids both reflection and Dynamic, which are usually considered bad practice.

like image 122
Gama11 Avatar answered Sep 20 '22 22:09

Gama11


You could create Map and fill it via Reflect api:

var parse = haxe.Json.parse(s);
var map:Map<String, StructData> = new Map();
for(field in Reflect.fields(parse))
{
    map.set(field, Reflect.field(parse, field));
}

typedef StructData = {
var value:Int;
var health:Int;
var tags:Array<String>;
}

https://try.haxe.org/#DFa77

like image 45
Andrew Avatar answered Sep 20 '22 22:09

Andrew


Take a look at the DynamicAccess abstract here.

Given your sample I've made a quick example here:

import haxe.DynamicAccess;

typedef Food = {
    var value:Int;
    var health:Int;
    var tags:Array<String>;
}

class Test {
    static function main() {
        var json = {
          "apple": {
            "value": 10,
            "health": 15,
            "tags": [
              "fruit",
              "fiber",
              "sweet"
            ]
          },
          "lemon": {
            "value": 5,
            "health": 10,
            "tags": [
              "fruit",
              "citrus",
              "sour"
            ]
          },
          "ham": {
            "value": 50,
            "health": 50,
            "tags": [
              "salty",
              "meat"
            ]
          }
        };

        var foodMap:DynamicAccess<Food> = json;

        // Get a single entry
        var apple = foodMap.get("apple");
        trace(apple.tags.join(", "));

        // Loop through names
        for (foodName in foodMap.keys()) {
            trace(foodName);
            trace(foodMap.get(foodName).value);
        }  
    }
}
like image 32
Christopher Mandlbaur Avatar answered Sep 18 '22 22:09

Christopher Mandlbaur