using System.Collections.Generic;
using Newtonsoft.Json.Linq;
public static void Main()
""AttachedTaskLocations"": [
Console.WriteLine("Deserializing AnchorMetaData from JSON");
var metaData = JsonConvert.DeserializeObject<AnchorMetaData>(json);
Console.WriteLine("Dumping AttachedTaskLocations list");
if (metaData.AttachedTaskLocations.Any())
foreach (Vector3 vector in metaData.AttachedTaskLocations)
Console.WriteLine(vector);
Console.WriteLine("AttachedTaskLocations list is empty!");
Console.WriteLine("Serializing back to JSON");
json = JsonConvert.SerializeObject(metaData, Formatting.Indented);
public class AnchorMetaData
[JsonProperty("AttachedTaskLocations", ItemConverterType = typeof(Vector3Converter))]
public List<Vector3> AttachedTaskLocations { get; set; } = new List<Vector3>();
public class Vector3Converter : JsonConverter
public override bool CanConvert(Type objectType)
return objectType == typeof(Vector3);
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
if (reader.TokenType == JsonToken.StartObject)
JObject obj = JObject.Load(reader);
return new Vector3((float)obj["x"], (float)obj["y"], (float)obj["z"]);
if (reader.TokenType == JsonToken.Null)
throw new JsonException("Unexpected token type: " + reader.TokenType);
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
Vector3 vector = (Vector3)value;
JObject obj = new JObject(
new JProperty("x", vector.x),
new JProperty("y", vector.y),
new JProperty("z", vector.z)
JValue.CreateNull().WriteTo(writer);
public partial struct Vector3 : IEquatable<Vector3>
public const float kEpsilon = 0.00001F;
public Vector3(float x, float y, float z) { this.x = x; this.y = y; this.z = z; }
public Vector3(float x, float y) { this.x = x; this.y = y; z = 0F; }
public void Set(float newX, float newY, float newZ) { x = newX; y = newY; z = newZ; }
public override int GetHashCode()
return x.GetHashCode() ^ (y.GetHashCode() << 2) ^ (z.GetHashCode() >> 2);
public override bool Equals(object other)
if (!(other is Vector3)) return false;
return Equals((Vector3)other);
public bool Equals(Vector3 other)
return x == other.x && y == other.y && z == other.z;
public Vector3 normalized
public float magnitude { get { return (float)Math.Sqrt(x * x + y * y + z * z); } }
public float sqrMagnitude { get { return x * x + y * y + z * z; } }
static readonly Vector3 zeroVector = new Vector3(0F, 0F, 0F);
static readonly Vector3 oneVector = new Vector3(1F, 1F, 1F);
static readonly Vector3 positiveInfinityVector = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
static readonly Vector3 negativeInfinityVector = new Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity);
public static Vector3 zero { get { return zeroVector; } }
public static Vector3 one { get { return oneVector; } }
public static Vector3 positiveInfinity { get { return positiveInfinityVector; } }
public static Vector3 negativeInfinity { get { return negativeInfinityVector; } }
public static Vector3 operator +(Vector3 a, Vector3 b) { return new Vector3(a.x + b.x, a.y + b.y, a.z + b.z); }
public static Vector3 operator -(Vector3 a, Vector3 b) { return new Vector3(a.x - b.x, a.y - b.y, a.z - b.z); }
public static Vector3 operator -(Vector3 a) { return new Vector3(-a.x, -a.y, -a.z); }
public static Vector3 operator *(Vector3 a, float d) { return new Vector3(a.x * d, a.y * d, a.z * d); }
public static Vector3 operator *(float d, Vector3 a) { return new Vector3(a.x * d, a.y * d, a.z * d); }
public static Vector3 operator /(Vector3 a, float d) { return new Vector3(a.x / d, a.y / d, a.z / d); }
public static bool operator ==(Vector3 lhs, Vector3 rhs)
float diff_x = lhs.x - rhs.x;
float diff_y = lhs.y - rhs.y;
float diff_z = lhs.z - rhs.z;
float sqrmag = diff_x * diff_x + diff_y * diff_y + diff_z * diff_z;
return sqrmag < kEpsilon * kEpsilon;
public static bool operator !=(Vector3 lhs, Vector3 rhs)
public override string ToString()
return $"Vector3 ({x}, {y}, {z})";