diff --git a/SharpNBT/Tags/ArrayTag.cs b/SharpNBT/Tags/ArrayTag.cs
index 71f3ec6..754f73d 100644
--- a/SharpNBT/Tags/ArrayTag.cs
+++ b/SharpNBT/Tags/ArrayTag.cs
@@ -2,8 +2,6 @@
using System.Collections;
using System.Collections.Generic;
using System.Numerics;
-using System.Runtime.CompilerServices;
-using System.Runtime.Serialization;
using System.Text;
using JetBrains.Annotations;
@@ -13,7 +11,7 @@ namespace SharpNBT;
/// Base class for NBT tags that contain a fixed-size array of numeric types.
///
/// A value type that implements .
-[PublicAPI][Serializable]
+[PublicAPI]
public abstract class ArrayTag : Tag, IReadOnlyList where T : unmanaged, INumber
{
///
@@ -35,22 +33,6 @@ protected ArrayTag(TagType type, string? name, T[] value) : base(type, name)
array = value;
}
- ///
- protected ArrayTag(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- var _ = info.GetInt32("count");
- var value = info.GetValue("values", typeof(T[])) as T[];
- array = value ?? Array.Empty();
- }
-
- ///
- public override void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- base.GetObjectData(info, context);
- info.AddValue("count", array.Length);
- info.AddValue("values", array);
- }
-
///
public IEnumerator GetEnumerator()
{
diff --git a/SharpNBT/Tags/BoolTag.cs b/SharpNBT/Tags/BoolTag.cs
index 2bf0591..172a796 100644
--- a/SharpNBT/Tags/BoolTag.cs
+++ b/SharpNBT/Tags/BoolTag.cs
@@ -1,5 +1,5 @@
using System;
-using System.Runtime.Serialization;
+using System.Text.Json;
using JetBrains.Annotations;
namespace SharpNBT;
@@ -11,7 +11,7 @@ namespace SharpNBT;
/// This tag type does not exist in the NBT specification, and is included for convenience to differentiate it from the that it is
/// actually serialized as.
///
-[PublicAPI][Serializable]
+[PublicAPI]
[Obsolete("Use the IsBool and Bool properties of ByteTag. This class will be removed in a future version.")]
public class BoolTag : Tag
{
@@ -26,16 +26,20 @@ public BoolTag(string? name, bool value) : base(TagType.Byte, name)
{
Value = value;
}
-
- ///
- /// Required constructor for ISerializable implementation.
- ///
- /// The to describing this instance.
- /// The destination (see ) for this serialization.
- protected BoolTag(SerializationInfo info, StreamingContext context) : base(info, context)
+
+ ///
+ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = true)
{
+ if (named && Name != null)
+ {
+ writer.WriteBoolean(Name, Value);
+ }
+ else
+ {
+ writer.WriteBooleanValue(Value);
+ }
}
-
+
///
public override string ToString() => $"TAG_Byte({PrettyName}): {(Value ? "true" : "false")}";
diff --git a/SharpNBT/Tags/ByteArrayTag.cs b/SharpNBT/Tags/ByteArrayTag.cs
index 0d27a75..80b671c 100644
--- a/SharpNBT/Tags/ByteArrayTag.cs
+++ b/SharpNBT/Tags/ByteArrayTag.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Runtime.Serialization;
+using System.Text.Json;
using JetBrains.Annotations;
namespace SharpNBT;
@@ -13,7 +13,7 @@ namespace SharpNBT;
/// While this class uses the CLS compliant (0..255), the NBT specification uses a signed value with a range of -128..127, so ensure
/// the bits are equivalent for your values.
///
-[PublicAPI][Serializable]
+[PublicAPI]
public class ByteArrayTag : ArrayTag
{
///
@@ -51,16 +51,24 @@ public ByteArrayTag(string? name, IEnumerable values) : base(TagType.ByteA
public ByteArrayTag(string? name, ReadOnlySpan values) : base(TagType.ByteArray, name, values.ToArray())
{
}
-
- ///
- /// Required constructor for ISerializable implementation.
- ///
- /// The to describing this instance.
- /// The destination (see ) for this serialization.
- protected ByteArrayTag(SerializationInfo info, StreamingContext context) : base(info, context)
+
+ ///
+ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = true)
{
+ if (named && Name != null)
+ {
+ writer.WriteStartArray(Name);
+ }
+ else
+ {
+ writer.WriteStartArray();
+ }
+
+ for (var i = 0; i < Count; i++)
+ writer.WriteNumberValue(this[i]);
+ writer.WriteEndArray();
}
-
+
///
public override string ToString()
{
diff --git a/SharpNBT/Tags/ByteTag.cs b/SharpNBT/Tags/ByteTag.cs
index 6c1360b..ec702d2 100644
--- a/SharpNBT/Tags/ByteTag.cs
+++ b/SharpNBT/Tags/ByteTag.cs
@@ -1,5 +1,5 @@
using System;
-using System.Runtime.Serialization;
+using System.Text.Json;
using JetBrains.Annotations;
namespace SharpNBT;
@@ -86,15 +86,6 @@ public ByteTag(string? name, bool value) : base(TagType.Byte, name, value ? (byt
public ByteTag(string? name, sbyte value) : base(TagType.Byte, name, unchecked((byte) value))
{
}
-
- ///
- /// Required constructor for ISerializable implementation.
- ///
- /// The to describing this instance.
- /// The destination (see ) for this serialization.
- protected ByteTag(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
///
public override string ToString()
@@ -102,6 +93,22 @@ public override string ToString()
object obj = IsBool ? Bool : Value;
return $"TAG_Byte({PrettyName}): {obj}";
}
+
+ ///
+ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = true)
+ {
+ if (named && Name != null)
+ {
+ if (IsBool)
+ writer.WriteBoolean(Name, Bool);
+ else
+ writer.WriteNumber(Name, Value);
+ }
+ else
+ {
+ writer.WriteNumberValue(Value);
+ }
+ }
///
/// Implicit conversion of this tag to a .
diff --git a/SharpNBT/Tags/CompoundTag.cs b/SharpNBT/Tags/CompoundTag.cs
index fded242..fbc87d5 100644
--- a/SharpNBT/Tags/CompoundTag.cs
+++ b/SharpNBT/Tags/CompoundTag.cs
@@ -3,8 +3,8 @@
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
-using System.Runtime.Serialization;
using System.Text;
+using System.Text.Json;
using JetBrains.Annotations;
namespace SharpNBT;
@@ -16,7 +16,7 @@ namespace SharpNBT;
/// This along with the class define the structure of the NBT format. Children are not order-dependent, nor is order guaranteed. The
/// closing does not require to be explicitly added, it will be added automatically during serialization.
///
-[PublicAPI][Serializable]
+[PublicAPI]
public class CompoundTag : Tag, IDictionary, ICollection
{
private readonly Dictionary dict;
@@ -42,25 +42,7 @@ public CompoundTag(string? name, IEnumerable values) : this(name)
dict.Add(value.Name!, AssertName(value));
}
}
-
- ///
- /// Required constructor for ISerializable implementation.
- ///
- /// The to describing this instance.
- /// The destination (see ) for this serialization.
- protected CompoundTag(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- var result = info.GetValue("children", typeof(Dictionary)) as Dictionary;
- dict = result ?? new Dictionary();
- }
-
- ///
- public override void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- base.GetObjectData(info, context);
- info.AddValue("children", dict);
- }
-
+
///
void ICollection>.Add(KeyValuePair item) => dict.Add(item.Key, item.Value);
@@ -157,6 +139,23 @@ public TTag Get(string name) where TTag : Tag
return (TTag)dict[name];
}
+ ///
+ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = true)
+ {
+ if (named && Name != null)
+ {
+ writer.WriteStartObject(Name);
+ }
+ else
+ {
+ writer.WriteStartObject();
+ }
+
+ foreach (var child in dict.Values)
+ child.WriteJson(writer, true);
+ writer.WriteEndObject();
+ }
+
/// Returns a string that represents the current object.
/// A string that represents the current object.
///
@@ -184,18 +183,18 @@ public string PrettyPrinted(string? indent = " ")
/// The name of the tag to search for.
/// to recursively search children, otherwise to only search direct descendants.
/// The first tag found with , otherwise if none was found.
- public Tag? Find(string name, bool recursive = false)
+ public TTag? Find(string name, bool recursive = false) where TTag : Tag
{
- foreach (var tag in dict.Values)
+ foreach (var (key, value) in dict)
{
- if (string.CompareOrdinal(name, tag.Name) == 0)
- return tag;
+ if (string.CompareOrdinal(name, key) == 0 && value is TTag result)
+ return result;
- if (recursive && tag is CompoundTag child)
+ if (recursive && value is CompoundTag child)
{
- var result = child.Find(name, true);
- if (result != null)
- return result;
+ var nested = child.Find(name, recursive);
+ if (nested != null)
+ return nested;
}
}
diff --git a/SharpNBT/Tags/DoubleTag.cs b/SharpNBT/Tags/DoubleTag.cs
index 08559f9..660241d 100644
--- a/SharpNBT/Tags/DoubleTag.cs
+++ b/SharpNBT/Tags/DoubleTag.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Runtime.Serialization;
+using System.Text.Json;
using JetBrains.Annotations;
namespace SharpNBT;
@@ -7,7 +6,7 @@ namespace SharpNBT;
///
/// A tag that contains a single IEEE-754 double-precision floating point number.
///
-[PublicAPI][Serializable]
+[PublicAPI]
public class DoubleTag : NumericTag
{
///
@@ -18,14 +17,18 @@ public class DoubleTag : NumericTag
public DoubleTag(string? name, double value) : base(TagType.Double, name, value)
{
}
-
- ///
- /// Required constructor for ISerializable implementation.
- ///
- /// The to describing this instance.
- /// The destination (see ) for this serialization.
- protected DoubleTag(SerializationInfo info, StreamingContext context) : base(info, context)
+
+ ///
+ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = true)
{
+ if (named && Name != null)
+ {
+ writer.WriteNumber(Name, Value);
+ }
+ else
+ {
+ writer.WriteNumberValue(Value);
+ }
}
///
diff --git a/SharpNBT/Tags/EndTag.cs b/SharpNBT/Tags/EndTag.cs
index 5ab9c82..2bcff26 100644
--- a/SharpNBT/Tags/EndTag.cs
+++ b/SharpNBT/Tags/EndTag.cs
@@ -1,4 +1,5 @@
using System.Text;
+using System.Text.Json;
using JetBrains.Annotations;
namespace SharpNBT;
@@ -15,7 +16,13 @@ public sealed class EndTag : Tag
public EndTag() : base(TagType.End, null)
{
}
-
+
+ ///
+ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = true)
+ {
+ // Do nothing
+ }
+
///
public override string ToString() => $"TAG_End";
diff --git a/SharpNBT/Tags/FloatTag.cs b/SharpNBT/Tags/FloatTag.cs
index 813d8b5..4c0fd99 100644
--- a/SharpNBT/Tags/FloatTag.cs
+++ b/SharpNBT/Tags/FloatTag.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Runtime.Serialization;
+using System.Text.Json;
using JetBrains.Annotations;
namespace SharpNBT;
@@ -7,7 +6,7 @@ namespace SharpNBT;
///
/// A tag that contains a single IEEE-754 single-precision floating point number.
///
-[PublicAPI][Serializable]
+[PublicAPI]
public class FloatTag : NumericTag
{
///
@@ -18,13 +17,18 @@ public class FloatTag : NumericTag
public FloatTag(string? name, float value) : base(TagType.Float, name, value)
{
}
- ///
- /// Required constructor for ISerializable implementation.
- ///
- /// The to describing this instance.
- /// The destination (see ) for this serialization.
- protected FloatTag(SerializationInfo info, StreamingContext context) : base(info, context)
+
+ ///
+ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = true)
{
+ if (named && Name != null)
+ {
+ writer.WriteNumber(Name, Value);
+ }
+ else
+ {
+ writer.WriteNumberValue(Value);
+ }
}
///
diff --git a/SharpNBT/Tags/IntArrayTag.cs b/SharpNBT/Tags/IntArrayTag.cs
index fc9b965..bca5e56 100644
--- a/SharpNBT/Tags/IntArrayTag.cs
+++ b/SharpNBT/Tags/IntArrayTag.cs
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
+using System.Text.Json;
using JetBrains.Annotations;
namespace SharpNBT;
@@ -9,7 +10,7 @@ namespace SharpNBT;
///
/// A tag that whose value is a contiguous sequence of 32-bit integers.
///
-[PublicAPI][Serializable]
+[PublicAPI]
public class IntArrayTag : ArrayTag
{
///
@@ -48,14 +49,22 @@ public IntArrayTag(string? name, IEnumerable values) : base(TagType.IntArra
public IntArrayTag(string? name, ReadOnlySpan values) : base(TagType.IntArray, name, values.ToArray())
{
}
-
- ///
- /// Required constructor for ISerializable implementation.
- ///
- /// The to describing this instance.
- /// The destination (see ) for this serialization.
- protected IntArrayTag(SerializationInfo info, StreamingContext context) : base(info, context)
+
+ ///
+ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = true)
{
+ if (named && Name != null)
+ {
+ writer.WriteStartArray(Name);
+ }
+ else
+ {
+ writer.WriteStartArray();
+ }
+
+ for (var i = 0; i < Count; i++)
+ writer.WriteNumberValue(this[i]);
+ writer.WriteEndArray();
}
///
diff --git a/SharpNBT/Tags/IntTag.cs b/SharpNBT/Tags/IntTag.cs
index a62a117..56e8e4b 100644
--- a/SharpNBT/Tags/IntTag.cs
+++ b/SharpNBT/Tags/IntTag.cs
@@ -1,5 +1,5 @@
using System;
-using System.Runtime.Serialization;
+using System.Text.Json;
using JetBrains.Annotations;
namespace SharpNBT;
@@ -7,7 +7,7 @@ namespace SharpNBT;
///
/// A tag that contains a single 32-bit integer value.
///
-[PublicAPI][Serializable]
+[PublicAPI]
public class IntTag : NumericTag
{
///
@@ -37,14 +37,18 @@ public IntTag(string? name, int value) : base(TagType.Int, name, value)
public IntTag(Tag? parent, string? name, uint value) : base(TagType.Int, name, unchecked((int) value))
{
}
-
- ///
- /// Required constructor for ISerializable implementation.
- ///
- /// The to describing this instance.
- /// The destination (see ) for this serialization.
- protected IntTag(SerializationInfo info, StreamingContext context) : base(info, context)
+
+ ///
+ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = true)
{
+ if (named && Name != null)
+ {
+ writer.WriteNumber(Name, Value);
+ }
+ else
+ {
+ writer.WriteNumberValue(Value);
+ }
}
///
diff --git a/SharpNBT/Tags/ListTag.cs b/SharpNBT/Tags/ListTag.cs
index c152055..c976ae8 100644
--- a/SharpNBT/Tags/ListTag.cs
+++ b/SharpNBT/Tags/ListTag.cs
@@ -2,8 +2,8 @@
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
-using System.Runtime.Serialization;
using System.Text;
+using System.Text.Json;
using JetBrains.Annotations;
namespace SharpNBT;
@@ -14,7 +14,7 @@ namespace SharpNBT;
///
/// All child tags must be have the same value, and their value will be omitted during serialization.
///
-[PublicAPI][Serializable]
+[PublicAPI]
public class ListTag : Tag, IList
{
///
@@ -56,28 +56,6 @@ public ListTag(string? name, TagType childType, IEnumerable children) : thi
foreach (var item in children)
list.Add(AssertType(item));
}
-
- ///
- /// Required constructor for ISerializable implementation.
- ///
- /// The to describing this instance.
- /// The destination (see ) for this serialization.
- protected ListTag(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- ChildType = (TagType)info.GetByte("child_type");
- var count = info.GetInt32("count");
- list = new List(count);
- if (info.GetValue("values", typeof(Tag[])) is Tag[] ary)
- AddRange(ary);
- }
-
- public override void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- base.GetObjectData(info, context);
- info.AddValue("child_type", (byte) ChildType);
- info.AddValue("count", list.Count);
- info.AddValue("values", list.ToArray());
- }
///
public IEnumerator GetEnumerator() => list.GetEnumerator();
@@ -128,24 +106,22 @@ public Tag this[int index]
set => list[index] = AssertType(value);
}
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ ///
+ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = true)
+ {
+ if (named && Name != null)
+ {
+ writer.WriteStartArray(Name);
+ }
+ else
+ {
+ writer.WriteStartArray();
+ }
+
+ for (var i = 0; i < Count; i++)
+ list[i].WriteJson(writer, false);
+ writer.WriteEndArray();
+ }
///
public override string ToString()
@@ -153,9 +129,7 @@ public override string ToString()
var word = Count == 1 ? Strings.WordEntry : Strings.WordEntries;
return $"TAG_List({PrettyName}): [{Count} {word}]";
}
-
-
-
+
///
protected internal override void PrettyPrinted(StringBuilder buffer, int level, string indent)
{
diff --git a/SharpNBT/Tags/LongArrayTag.cs b/SharpNBT/Tags/LongArrayTag.cs
index 609e4da..87171a4 100644
--- a/SharpNBT/Tags/LongArrayTag.cs
+++ b/SharpNBT/Tags/LongArrayTag.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Runtime.Serialization;
+using System.Text.Json;
using JetBrains.Annotations;
namespace SharpNBT;
@@ -9,7 +9,7 @@ namespace SharpNBT;
///
/// A tag that whose value is a contiguous sequence of 64-bit integers.
///
-[PublicAPI][Serializable]
+[PublicAPI]
public class LongArrayTag : ArrayTag
{
///
@@ -29,15 +29,6 @@ public LongArrayTag(string? name, long[] values) : base(TagType.LongArray, name,
{
}
- ///
- /// Required constructor for ISerializable implementation.
- ///
- /// The to describing this instance.
- /// The destination (see ) for this serialization.
- protected LongArrayTag(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- }
-
///
/// Initializes a new instance of the with the specified .
///
@@ -55,6 +46,23 @@ public LongArrayTag(string? name, IEnumerable values) : base(TagType.LongA
public LongArrayTag(string? name, ReadOnlySpan values) : base(TagType.LongArray, name, values.ToArray())
{
}
+
+ ///
+ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = true)
+ {
+ if (named && Name != null)
+ {
+ writer.WriteStartArray(Name);
+ }
+ else
+ {
+ writer.WriteStartArray();
+ }
+
+ for (var i = 0; i < Count; i++)
+ writer.WriteNumberValue(this[i]);
+ writer.WriteEndArray();
+ }
///
public override string ToString()
diff --git a/SharpNBT/Tags/LongTag.cs b/SharpNBT/Tags/LongTag.cs
index c118130..e14e60b 100644
--- a/SharpNBT/Tags/LongTag.cs
+++ b/SharpNBT/Tags/LongTag.cs
@@ -1,5 +1,5 @@
using System;
-using System.Runtime.Serialization;
+using System.Text.Json;
using JetBrains.Annotations;
namespace SharpNBT;
@@ -7,7 +7,7 @@ namespace SharpNBT;
///
/// A tag that contains a single 64-bit integer value.
///
-[PublicAPI][Serializable]
+[PublicAPI]
public class LongTag : NumericTag
{
///
@@ -37,14 +37,18 @@ public LongTag(string? name, long value) : base(TagType.Long, name, value)
public LongTag(string? name, ulong value) : base(TagType.Long, name, unchecked((long) value))
{
}
-
- ///
- /// Required constructor for ISerializable implementation.
- ///
- /// The to describing this instance.
- /// The destination (see ) for this serialization.
- protected LongTag(SerializationInfo info, StreamingContext context) : base(info, context)
+
+ ///
+ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = true)
{
+ if (named && Name != null)
+ {
+ writer.WriteNumber(Name, Value);
+ }
+ else
+ {
+ writer.WriteNumberValue(Value);
+ }
}
///
diff --git a/SharpNBT/Tags/NumericTag.cs b/SharpNBT/Tags/NumericTag.cs
index 22d023a..944deef 100644
--- a/SharpNBT/Tags/NumericTag.cs
+++ b/SharpNBT/Tags/NumericTag.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Numerics;
-using System.Runtime.Serialization;
+using System.Text.Json;
using JetBrains.Annotations;
namespace SharpNBT;
@@ -10,7 +10,7 @@ namespace SharpNBT;
/// Abstract base class for types that contain a single numeric value.
///
/// A value type that implements .
-[PublicAPI][Serializable]
+[PublicAPI]
public abstract class NumericTag : Tag, IEquatable>, IComparable>, IComparable where T : unmanaged, INumber
{
///
@@ -23,21 +23,7 @@ protected NumericTag(TagType type, string? name, T value) : base(type, name)
{
Value = value;
}
-
- ///
- protected NumericTag(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- var value = info.GetValue("value", typeof(T));
- Value = value is null ? default : (T)value;
- }
- ///
- public override void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- base.GetObjectData(info, context);
- info.AddValue("value", Value, typeof(T));
- }
-
///
public bool Equals(NumericTag? other)
{
diff --git a/SharpNBT/Tags/ShortTag.cs b/SharpNBT/Tags/ShortTag.cs
index 7a6a1ae..cb71678 100644
--- a/SharpNBT/Tags/ShortTag.cs
+++ b/SharpNBT/Tags/ShortTag.cs
@@ -1,5 +1,5 @@
using System;
-using System.Runtime.Serialization;
+using System.Text.Json;
using JetBrains.Annotations;
namespace SharpNBT;
@@ -7,7 +7,7 @@ namespace SharpNBT;
///
/// A tag that contains a single 16-bit integer value.
///
-[PublicAPI][Serializable]
+[PublicAPI]
public class ShortTag : NumericTag
{
///
@@ -43,14 +43,18 @@ public ShortTag(string? name, int value) : base(TagType.Short, name, unchecked((
public ShortTag(string? name, ushort value) : base(TagType.Short, name, unchecked((short) value))
{
}
-
- ///
- /// Required constructor for ISerializable implementation.
- ///
- /// The to describing this instance.
- /// The destination (see ) for this serialization.
- protected ShortTag(SerializationInfo info, StreamingContext context) : base(info, context)
+
+ ///
+ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = true)
{
+ if (named && Name != null)
+ {
+ writer.WriteNumber(Name, Value);
+ }
+ else
+ {
+ writer.WriteNumberValue(Value);
+ }
}
///
diff --git a/SharpNBT/Tags/StringTag.cs b/SharpNBT/Tags/StringTag.cs
index 7e5c05c..ed57705 100644
--- a/SharpNBT/Tags/StringTag.cs
+++ b/SharpNBT/Tags/StringTag.cs
@@ -1,6 +1,5 @@
using System;
-using System.Numerics;
-using System.Runtime.Serialization;
+using System.Text.Json;
using JetBrains.Annotations;
namespace SharpNBT;
@@ -8,7 +7,7 @@ namespace SharpNBT;
///
/// A tag the contains a UTF-8 string.
///
-[PublicAPI][Serializable]
+[PublicAPI]
public class StringTag : Tag, IEquatable
{
///
@@ -25,18 +24,18 @@ public StringTag(string? name, string? value) : base(TagType.String, name)
{
Value = value ?? string.Empty;
}
-
- ///
- protected StringTag(SerializationInfo info, StreamingContext context) : base(info, context)
- {
- Value = info.GetString("value") ?? string.Empty;
- }
-
+
///
- public override void GetObjectData(SerializationInfo info, StreamingContext context)
+ protected internal override void WriteJson(Utf8JsonWriter writer, bool named = true)
{
- base.GetObjectData(info, context);
- info.AddValue("value", Value);
+ if (named && Name != null)
+ {
+ writer.WriteString(Name, Value);
+ }
+ else
+ {
+ writer.WriteStringValue(Value);
+ }
}
///
diff --git a/SharpNBT/Tags/Tag.cs b/SharpNBT/Tags/Tag.cs
index 151069a..4f69f01 100644
--- a/SharpNBT/Tags/Tag.cs
+++ b/SharpNBT/Tags/Tag.cs
@@ -1,11 +1,10 @@
using System;
-using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Runtime.CompilerServices;
-using System.Runtime.Serialization;
-using System.Runtime.Serialization.Json;
using System.Text;
-using System.Text.RegularExpressions;
+using System.Text.Json;
+using System.Threading.Tasks;
using JetBrains.Annotations;
[assembly: CLSCompliant(true)]
@@ -16,40 +15,9 @@ namespace SharpNBT;
///
/// Abstract base class that all NBT tags inherit from.
///
-[PublicAPI][Serializable]
-public abstract class Tag : IEquatable, ISerializable, ICloneable
+[PublicAPI]
+public abstract class Tag : IEquatable, ICloneable
{
- private static Regex simpleNameMatcher;
-
- static Tag()
- {
- simpleNameMatcher = new Regex(@"^[A-Ba-z0-9_-]+$", RegexOptions.Compiled);
- }
-
-
- private static IEnumerable GetKnownTypes()
- {
- return new[]
- {
- typeof(TagType),
- typeof(NumericTag<>),
- typeof(ArrayTag<>),
- typeof(Tag[]),
- typeof(ByteTag),
- typeof(ShortTag),
- typeof(IntTag),
- typeof(LongTag),
- typeof(FloatTag),
- typeof(DoubleTag),
- typeof(StringTag),
- typeof(ByteArrayTag),
- typeof(IntArrayTag),
- typeof(LongArrayTag),
- typeof(ListTag),
- typeof(CompoundTag)
- };
- }
-
///
/// Text applied in a pretty-print sting when a tag has no defined value.
///
@@ -58,17 +26,18 @@ private static IEnumerable GetKnownTypes()
///
/// Gets a constant describing the NBT type this object represents.
///
- public TagType Type { get; private set; }
+ public TagType Type { get; }
///
/// Gets the parent this object is a child of.
///
+ [Obsolete("Parent property will be removed in a future version.")]
public Tag? Parent { get; internal set; }
///
/// Gets the name assigned to this .
///
- public string? Name { get; set; }
+ public string? Name { get; }
///
/// Initialized a new instance of the class.
@@ -98,77 +67,115 @@ protected internal virtual void PrettyPrinted(StringBuilder buffer, int level, s
/// Gets the name of the object as a human-readable quoted string, or a default name to indicate it has no name when applicable.
///
protected internal string PrettyName => Name is null ? "None" : $"\"{Name}\"";
-
+
///
- /// Gets a representation of this as a JSON string.
+ /// Uses the provided to write the NBT tag in JSON format.
///
- /// Flag indicating if formatting should be applied to make the string human-readable.
- /// When is , indicates the indent characters(s) to use.
- /// A JSON string describing this object.
- public string ToJsonString(bool pretty = false, string indent = " ")
+ /// A JSON writer instance.
+ ///
+ /// Flag indicating if this object's name should be written as a property name, or when it
+ /// is a child of , in which case it should be written as a JSON array element.
+ ///
+ protected internal abstract void WriteJson(Utf8JsonWriter writer, bool named = true);
+
+ ///
+ /// Writes the tag to the specified in JSON format.
+ ///
+ /// The stream instance to write to.
+ /// Options that will be passed to the JSON writer.
+ /// The stream is no opened for writing.
+ public void WriteJson(Stream stream, JsonWriterOptions? options = null)
{
- var settings = new DataContractJsonSerializerSettings
+ using var json = new Utf8JsonWriter(stream, options ?? new JsonWriterOptions());
+
+ if (string.IsNullOrEmpty(Name))
{
- UseSimpleDictionaryFormat = true,
- EmitTypeInformation = EmitTypeInformation.Never,
- KnownTypes = GetKnownTypes()
- };
- var serializer = new DataContractJsonSerializer(typeof(Tag), settings);
- using var stream = new MemoryStream();
- if (pretty)
+ json.WriteStartArray();
+ WriteJson(json, false);
+ json.WriteEndArray();
+ }
+ else
+ {
+ json.WriteStartObject();
+ WriteJson(json, true);
+ json.WriteEndObject();
+ }
+
+ json.Flush();
+ }
+
+ ///
+ /// Asynchronously writes the tag to the specified in JSON format.
+ ///
+ /// The stream instance to write to.
+ /// Options that will be passed to the JSON writer.
+ /// The stream is no opened for writing.
+ public async Task WriteJsonAsync(Stream stream, JsonWriterOptions? options = null)
+ {
+ await using var json = new Utf8JsonWriter(stream, options ?? new JsonWriterOptions());
+
+ if (string.IsNullOrEmpty(Name))
{
- using var writer = JsonReaderWriterFactory.CreateJsonWriter(stream, Encoding.UTF8, false, true, indent);
- serializer.WriteObject(writer, this);
- writer.Flush();
+ json.WriteStartArray();
+ WriteJson(json, false);
+ json.WriteEndArray();
}
else
{
- serializer.WriteObject(stream, this);
+ json.WriteStartObject();
+ WriteJson(json, true);
+ json.WriteEndObject();
}
+
+ await json.FlushAsync();
+ }
+
+ ///
+ /// Converts the NBT to an equivalent JSON representation, and returns it as a string.
+ ///
+ /// Options that will be passed to the JSON writer.
+ /// The JSON-encoded string representing describing the tag.
+ public string ToJson(JsonWriterOptions? options = null)
+ {
+ using var stream = new MemoryStream();
+ WriteJson(stream, options);
stream.Flush();
return Encoding.UTF8.GetString(stream.ToArray());
}
+
+ ///
+ /// Gets a representation of this as a JSON string.
+ ///
+ /// Flag indicating if formatting should be applied to make the string human-readable.
+ /// Ignored
+ /// A JSON string describing this object.
+ [Obsolete("Use WriteJson and ToJson instead.")]
+ public string ToJsonString(bool pretty = false, string indent = " ")
+ {
+ var options = new JsonWriterOptions { Indented = pretty };
+ return ToJson(options);
+ }
- /// Indicates whether the current object is equal to another object of the same type.
- /// An object to compare with this object.
- ///
- /// if the current object is equal to the parameter; otherwise, .
- ///
+ ///
public bool Equals(Tag? other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
- return Type == other.Type && Name == other.Name;
+ return Type == other.Type && string.CompareOrdinal(Name, other.Name) == 0;
}
- /// Determines whether the specified object is equal to the current object.
- /// The object to compare with the current object.
- ///
- /// if the specified object is equal to the current object; otherwise, .
- ///
+ ///
public override bool Equals(object? obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
- if (obj.GetType() != this.GetType()) return false;
- return Equals((Tag)obj);
- }
-
- /// Serves as the default hash function.
- /// A hash code for the current object.
- ///
- public override int GetHashCode()
- {
- unchecked
- {
- // ReSharper disable NonReadonlyMemberInGetHashCode
- return ((int)Type * 373) ^ (Name != null ? Name.GetHashCode() : 0);
- // ReSharper restore NonReadonlyMemberInGetHashCode
- }
+ return obj.GetType() == GetType() && Equals((Tag)obj);
}
- /// Creates a new object that is a copy of the current instance.
- /// A new object that is a copy of this instance.
+ ///
+ public override int GetHashCode() => HashCode.Combine((int)Type, Name);
+
+ ///
public object Clone()
{
// Serialize then deserialize to make a deep-copy
@@ -182,28 +189,7 @@ public object Clone()
writer.WriteTag(this);
stream.Seek(0, SeekOrigin.Begin);
- return reader.ReadTag(!(Parent is ListTag));
- }
-
- ///
- /// Required constructor for ISerializable implementation.
- ///
- /// The to describing this instance.
- /// The destination (see ) for this serialization.
- protected Tag(SerializationInfo info, StreamingContext context)
- {
- Type = (TagType) info.GetByte("type");
- Name = info.GetString("name");
- }
-
- /// Populates a with the data needed to serialize the target object.
- /// The to populate with data.
- /// The destination (see ) for this serialization.
- /// The caller does not have the required permission.
- public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
- {
- info.AddValue("type", (byte) Type);
- info.AddValue("name", Name);
+ return reader.ReadTag(!string.IsNullOrWhiteSpace(Name));
}
///
@@ -238,7 +224,7 @@ protected internal string StringifyName
{
if (string.IsNullOrEmpty(Name))
return string.Empty;
- return simpleNameMatcher.IsMatch(Name) ? Name : $"\"{Name}\"";
+ return Name.All(c => c.IsValidUnquoted()) ? Name : $"\"{Name}\"";
}
}
}
\ No newline at end of file