static void SerializeGltfMesh(Mesh &mesh, json &o) {
  json primitives;
  JsonReserveArray(primitives, mesh.primitives.size());
  for (unsigned int i = 0; i < mesh.primitives.size(); ++i) {
    json primitive;
    const Primitive &gltfPrimitive = mesh.primitives[i];  // don't make a copy
    {
      json attributes;
      for (auto attrIt = gltfPrimitive.attributes.begin();
           attrIt != gltfPrimitive.attributes.end(); ++attrIt) {
        SerializeNumberProperty<int>(attrIt->first, attrIt->second, attributes);
      }

      JsonAddMember(primitive, "attributes", std::move(attributes));
    }

    // Indicies is optional
    if (gltfPrimitive.indices > -1) {
      SerializeNumberProperty<int>("indices", gltfPrimitive.indices, primitive);
    }
    // Material is optional
    if (gltfPrimitive.material > -1) {
      SerializeNumberProperty<int>("material", gltfPrimitive.material,
                                   primitive);
    }
    SerializeNumberProperty<int>("mode", gltfPrimitive.mode, primitive);

    // Morph targets
    if (gltfPrimitive.targets.size()) {
      json targets;
      JsonReserveArray(targets, gltfPrimitive.targets.size());
      for (unsigned int k = 0; k < gltfPrimitive.targets.size(); ++k) {
        json targetAttributes;
        std::map<std::string, int> targetData = gltfPrimitive.targets[k];
        for (std::map<std::string, int>::iterator attrIt = targetData.begin();
             attrIt != targetData.end(); ++attrIt) {
          SerializeNumberProperty<int>(attrIt->first, attrIt->second,
                                       targetAttributes);
        }
        JsonPushBack(targets, std::move(targetAttributes));
      }
      JsonAddMember(primitive, "targets", std::move(targets));
    }

    SerializeExtensionMap(gltfPrimitive.extensions, primitive);

    if (gltfPrimitive.extras.Type() != NULL_TYPE) {
      SerializeValue("extras", gltfPrimitive.extras, primitive);
    }

    JsonPushBack(primitives, std::move(primitive));
  }

  JsonAddMember(o, "primitives", std::move(primitives));

  if (mesh.weights.size()) {
    SerializeNumberArrayProperty<double>("weights", mesh.weights, o);
  }

  if (mesh.name.size()) {
    SerializeStringProperty("name", mesh.name, o);
  }

  SerializeExtensionMap(mesh.extensions, o);
  if (mesh.extras.Type() != NULL_TYPE) {
    SerializeValue("extras", mesh.extras, o);
  }
}
static void SerializeGltfMesh(Mesh &mesh, json &o) {
  json primitives;
  JsonReserveArray(primitives, mesh.primitives.size());
  for (unsigned int i = 0; i < mesh.primitives.size(); ++i) {
    json primitive;
    const Primitive &gltfPrimitive = mesh.primitives[i];   
    {
      json attributes;
      for (auto attrIt = gltfPrimitive.attributes.begin();
           attrIt != gltfPrimitive.attributes.end(); ++attrIt) {
        SerializeNumberProperty<int>(attrIt->first, attrIt->second, attributes);
      }

      JsonAddMember(primitive, "attributes", std::move(attributes));
    }

     
    if (gltfPrimitive.indices > -1) {
      SerializeNumberProperty<int>("indices", gltfPrimitive.indices, primitive);
    }
     
    if (gltfPrimitive.material > -1) {
      SerializeNumberProperty<int>("material", gltfPrimitive.material,
                                   primitive);
    }
    SerializeNumberProperty<int>("mode", gltfPrimitive.mode, primitive);

     
    if (gltfPrimitive.targets.size()) {
      json targets;
      JsonReserveArray(targets, gltfPrimitive.targets.size());
      for (unsigned int k = 0; k < gltfPrimitive.targets.size(); ++k) {
        json targetAttributes;
        std::map<std::string, int> targetData = gltfPrimitive.targets[k];
        for (std::map<std::string, int>::iterator attrIt = targetData.begin();
             attrIt != targetData.end(); ++attrIt) {
          SerializeNumberProperty<int>(attrIt->first, attrIt->second,
                                       targetAttributes);
        }
        JsonPushBack(targets, std::move(targetAttributes));
      }
      JsonAddMember(primitive, "targets", std::move(targets));
    }

    SerializeExtensionMap(gltfPrimitive.extensions, primitive);

    if (gltfPrimitive.extras.Type() != NULL_TYPE) {
      SerializeValue("extras", gltfPrimitive.extras, primitive);
    }

    JsonPushBack(primitives, std::move(primitive));
  }

  JsonAddMember(o, "primitives", std::move(primitives));

  if (mesh.weights.size()) {
    SerializeNumberArrayProperty<double>("weights", mesh.weights, o);
  }

  if (mesh.name.size()) {
    SerializeStringProperty("name", mesh.name, o);
  }

  SerializeExtensionMap(mesh.extensions, o);
  if (mesh.extras.Type() != NULL_TYPE) {
    SerializeValue("extras", mesh.extras, o);
  }
}