Search Unity

  1. Unity Asset Manager is now available in public beta. Try it out now and join the conversation here in the forums.
    Dismiss Notice

Feedback Please add System.Text.Json support

Discussion in 'Experimental Scripting Previews' started by stopiccot_tds, Nov 5, 2020.

  1. stopiccot_tds

    stopiccot_tds

    Joined:
    Oct 1, 2016
    Posts:
    111
    Pretty self-describing
     
    CyberAngel and Pepe20129 like this.
  2. stopiccot_tds

    stopiccot_tds

    Joined:
    Oct 1, 2016
    Posts:
    111
    It lacks a lot of features of proper json serializer/deserializer.
     
    stonstad and phobos2077 like this.
  3. print_helloworld

    print_helloworld

    Joined:
    Nov 14, 2016
    Posts:
    231
    You can also point out why exactly you need that namespace, for example, by listing out the features.
     
    Last edited: Nov 9, 2020
  4. stopiccot_tds

    stopiccot_tds

    Joined:
    Oct 1, 2016
    Posts:
    111
  5. runner78

    runner78

    Joined:
    Mar 14, 2015
    Posts:
    792
    phobos2077 likes this.
  6. TheZombieKiller

    TheZombieKiller

    Joined:
    Feb 8, 2013
    Posts:
    266
    Note that you can still use System.Text.Json (alongside Span<T> and others) via the NuGet package. You just won't be able to take advantage of specific runtime optimizations associated with Span<T> and such. https://www.nuget.org/packages/System.Text.Json/
     
    phobos2077 likes this.
  7. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    Alverik and phobos2077 like this.
  8. print_helloworld

    print_helloworld

    Joined:
    Nov 14, 2016
    Posts:
    231
    Given that they want "features for proper json" then the newtonsoft variant is what they're looking for.
     
  9. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    *May work in Net 6 when reflection will be replaced with source generators :)
     
    stonstad likes this.
  10. punppiskamk

    punppiskamk

    Joined:
    Jan 11, 2021
    Posts:
    1
    They would also like to have lighweight solution. Serializing/Deserializing a very simple object could allocate memory of 10s to 100s of MBs. That's not really viable for mobile game development, or any development to be honest. You should not run out of memory because few kB JSON docs.
     
  11. poprev-3d

    poprev-3d

    Joined:
    Apr 12, 2019
    Posts:
    72
    System.Text.Json support would be greatly appreciated. The Unity serialization system (even the new one) lacks features. Newtonsoft.Json is too random and horrible performance-wise.

    System.Text.Json is a good alternative between maintainability, performance, and features. Right now it works on Mono builds but not on IL2CPP/WebGL builds, support for IL2CPP would be greatly appreciated.
     
    Cameo221, thexdd and phobos2077 like this.
  12. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    You may want to try the new features in this build: https://forum.unity.com/threads/il2cpp-build-time-improvements-seeking-feedback.1064135/

    This should avoid the AOT compilation errors that can come with System.Text.Json.
     
    phobos2077 likes this.
  13. bdovaz

    bdovaz

    Joined:
    Dec 10, 2011
    Posts:
    1,053
  14. Digika

    Digika

    Joined:
    Jan 7, 2018
    Posts:
    225
    That's kinda ironic, considering rewrite of .NET built-in JSON parses inspired by Utf2json and the creator was one of the top contributors to new netcode json library
     
  15. markinovus

    markinovus

    Joined:
    Apr 27, 2021
    Posts:
    5
    Sorry for dragging up an old thread but has anyone managed to get System.Text.Json working at all in Unity?
     
    stonstad likes this.
  16. poprev-3d

    poprev-3d

    Joined:
    Apr 12, 2019
    Posts:
    72
    @markinovus yes !

    You basically have to follow one to three steps, depending on your situation:
    • Gather the required DLL of System.Text.Json with the right version (using NuGet online website, then decompress the nuget package with 7Zip for example). Use the 5.0.0 version of System.Text.Json. You'll need to have all these Dlls:
      • Microsoft.Bcl.AsyncInterfaces.dll
      • System.Buffers.dll
      • System.Memory.dll
      • System.Runtime.CompilerServices.Unsafe.dll
      • System.Text.Encodings.Web.dll
      • System.Text.Json.dll
      • System.Threading.Tasks.Extensions.dll
    • For Il2CPP and WebGL: Add the following link.xml in the Asset folder
      • Code (CSharp):
        1. <linker>
        2.     <assembly fullname="System.Text.Json">
        3.         <namespace fullname="System.Text.Json" preserve="all" />
        4.         <namespace fullname="System.Text.Json.Serialization" preserve="all" />
        5.         <namespace fullname="System.Text.Json.Serialization.Converters" preserve="all" />
        6.     </assembly>
        7. </linker>
    • For Il2CPP and WebGL: You might have to write custom converters for very specific cases such as serializing generic function instances for value types. See the github thread : https://github.com/dotnet/runtime/issues/49772

     
    Last edited: Jan 11, 2022
  17. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    660
    Unity's serializer doesn't run server-side. An important use case is having the same tooling on the client and game server. Newtonsoft.Json works (and it is what I use) but it lacks the minimal allocation and high performance design of System.Text.Json.
     
  18. Laicasaane

    Laicasaane

    Joined:
    Apr 15, 2015
    Posts:
    363
    I've never used Unity's JSON serializer. It just lacks all the features I need. And now we just need all that features of Newtonsoft.JSON plus more performance.
     
  19. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
  20. Peter77

    Peter77

    QA Jesus

    Joined:
    Jun 12, 2013
    Posts:
    6,619
    Quoting my own post :)

    Unity Technologies provide Newtonsoft.JSON through the Package Manager by now. Just add the following line to
    Packages/manifest.json
    :
    "com.unity.nuget.newtonsoft-json": "2.0.0",
     
  21. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    It's outdated version of https://github.com/jilleJr/Newtonsoft.Json-for-Unity
     
    VOTRUBEC likes this.
  22. Laicasaane

    Laicasaane

    Joined:
    Apr 15, 2015
    Posts:
    363
    I suppose most of the people here asking for System.Text.Json are well aware of this already. However we are now in need of a better solution: higher perf, less allocation. You seem don't understand this point since the beginning?
     
  23. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    You too:
     
  24. Laicasaane

    Laicasaane

    Joined:
    Apr 15, 2015
    Posts:
    363
    I know about neuecc/Utf8Json actually, but didn't successfully use it 3 years ago. 2 years later my main concern changed, I worked mainly on offline games without json data. However, it's now changed again, I'm now working in an online game project. I see neuecc/Utf8Json has been inactive for a long time thus I just want to use something that is more actively maintained.
     
  25. paul-masri-stone

    paul-masri-stone

    Joined:
    Mar 23, 2020
    Posts:
    49
    I know from previous experience (non games applications) the value of including version numbering into JSON and version migration within the code, so that if the code is upgraded and the JSON structure changes then the app still works and can auto-migrate data saved from an older version to the current codebase.

    Unfortunately a limitation of JsonUtility is that it serializes/deserializes the current structure only. If you were to try deserializing data saved from an older version of code, it just wouldn't work.

    I want to have full JsonDocument control (as provided by System.Text.Json), the ability to include a version attribute that I can peek at before deserializing and the ability to manipulate the JSON as a structured object.

    As a temporary workaround, I am considering this approach:

    1. Include the JSON version as a hidden, serializable, private field in the object I want to serialize:
    Code (CSharp):
    1. [Serializable]
    2. public MyClass
    3. {
    4.     [SerializeField, HideInInspector]
    5.     private int _jsonVersion = 1;
    6.     ...

    2. Before deserializing, peek at the version number:
    Code (CSharp):
    1.     public void DeserializeJson(string json)
    2.     {
    3.         private struct JsonVersionStruct
    4.         {
    5.             public int _jsonVersion;
    6.         }
    7.  
    8.         var jsonVersionStruct = JsonUtility.FromJson<JsonVersionStruct>(json);
    9.         if (jsonVersionStruct._jsonVersion == _jsonVersion)
    10.         {
    11.             ...
    But this is a gnarly workaround when there's a perfectly good class in System.Text.Json.

    I like JsonUtility, but it's just too basic to trust with a production system.

    [EDIT: I originally had _jsonVersion as static in step 1 but this won't serialize.]
     
    Last edited: Oct 26, 2021
  26. stonstad

    stonstad

    Joined:
    Jan 19, 2018
    Posts:
    660
    Has anyone succeeded in getting System.Text.Json to run properly in Unity 2021.2?
     
  27. print_helloworld

    print_helloworld

    Joined:
    Nov 14, 2016
    Posts:
    231
    This exact use case has made me manually inject a $jsonVersion header into my json for my levels, and then an upgrading system where its able to take a file from version n and upgrade it match version n + 1 perfectly. If you chain all of the upgraders then you are able to take it from version 1 to version 24 assuming you implement all of the conversions. This does require you to handle the json structure correctly tho, so using something that is able to unflatten a json string can give you really good control, this is something that unity's jsonutility cant do. If it could unflatten json strings that would be amazing.
     
    paul-masri-stone likes this.
  28. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    Seems like System.Text.Json works in 2021.2.7, at least on windows (also il2cpp!) for this class (I've tried int as T):

    Code (CSharp):
    1. public class Obj<T>
    2. {
    3.     public string[] TestString {get; set;}
    4.     public InnerObj TestObj {get; set;}
    5.     public T TestT {get; set;}
    6.  
    7.     public class InnerObj
    8.     {
    9.         public string TestString {get; set;}
    10.     }
    11. }
     
    Thaina and stonstad like this.
  29. VolodymyrBS

    VolodymyrBS

    Joined:
    May 15, 2019
    Posts:
    150
    Which IL2CPP Code Generation option did you use?
     
    stonstad likes this.
  30. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    Both work.
     
  31. andyz

    andyz

    Joined:
    Jan 5, 2010
    Posts:
    2,276
  32. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    No, there is nothing official at the moment. FWIW we will be happy to look at bugs around System.Text.Json and try to fix them. It should "just work" like any other managed code, but clearly there are some difficulties.

    There are ongoing discussions within Unity about how to support and communicate JSON libraries from managed code. I expect that we will be able to get to a good place though.
     
    Alverik, AliAlbarrak and andyz like this.
  33. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    Last edited: Apr 25, 2022
    PrimePeter, Anthiese and Peter77 like this.
  34. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    With il2cpp "faster runtime" value types won't work (not sure about Unity 2022).

    @JoshPeterson Would 3rd il2cpp code generation option "faster runtime with full generics" be possible at cost of the biggest size?
     
  35. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    Just tried, seems to be working with il2cpp "faster runtime" even for value types. For ex.
    Code (CSharp):
    1. [JsonSerializable(typeof(MyStruct))]
    2. [JsonSerializable(typeof(MyStruct2))]
    3. public partial class MyJsonContext : JsonSerializerContext{}
    4.  
    5. public byte[] Method<T>(T obj) =>
    6.   JsonSerializer.SerializeToUtf8Bytes<T>(obj, MyJsonContext.Default.Options)
    Unfortunately "Options" field was added in later version of the source generator. Unity's Editor\Data\NetCoreRuntime and Editor\Data\DotNetSdkRoslyn have to be updated manually to get it working.
     
  36. JoshPeterson

    JoshPeterson

    Unity Technologies

    Joined:
    Jul 21, 2014
    Posts:
    6,938
    Yes, this is the default behavior of IL2CPP at Unity 2022.1 and later. The "faster runtime" option always generates a fall back path for value type generics that are not available at compile time. See this blog post for more details: https://blog.unity.com/technology/feature-preview-il2cpp-full-generic-sharing-in-unity-20221-beta
     
    Alverik, Kamyker and Anthiese like this.
  37. entem

    entem

    Joined:
    May 4, 2021
    Posts:
    3
    Did you manage to get json source generator to work? I couldn't implement JsonSerializerContext at all due to compiler errors.
     
  38. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    Yes but I ended up symlinking whatever .net sdk I have installed to Unity folder to not relay on their version. For ex. C:\Program Files\dotnet\sdk\6.0.401\Roslyn\bincore > Editor\Data\DotNetSdkRoslyn . This is discouraged by Unity but works for me fine.

    This way VS/Rider and Unity uses same sdk and allows me use the most recent versions of NuGet packages.
     
  39. atr0phy

    atr0phy

    Joined:
    Nov 5, 2014
    Posts:
    43
    What steps exactly do I need to take? That namespace fails to resolve for me using 2021 LTS with the latest nuget package.
     
  40. atr0phy

    atr0phy

    Joined:
    Nov 5, 2014
    Posts:
    43
    I'm not as knowledgeable in this particular realm as some of the folks in this thread. But as I understand it, Newtonsoft doesn't properly support async behavior. And never will. So unless I'm completely misunderstanding something, I struggle to understand why Unity has continued pushing support for this over System.Text.Json.
     
  41. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    You'll need a lot of dlls. You can try https://github.com/xoofx/UnityNuGet . I build nuget dlls using separate normal csproj but that plugin may be easier to use.
    Newtonsoft has 4x more nuget downloads than System.Text.Json, you can easily get async support by running it on separate thread (I like the using the UniTask.SwitchToThreadPool()).

    Unity is pushing for net 6 that will have nuget support and thus easy way to use System.Text.Json,
     
  42. atr0phy

    atr0phy

    Joined:
    Nov 5, 2014
    Posts:
    43
    Excellent this worked perfectly. Thanks for taking the time to point me in the right direction.

    That's a fair point. Performance is the primary consideration for my particular use case, which System.Text.Json seems to have the upper hand in as well.
     
  43. runner78

    runner78

    Joined:
    Mar 14, 2015
    Posts:
    792
    System.Text.Json is part of .Net 6 (since .NET core 3.0) the nuget package is for other versions and .NET standard.
    Since the new runtime will probably not come until 2023.2, it could also be that Unity comes with .NET 7, maybe even 8 Since .NET and Unity 202x.2 versions are released around the same time, that would be interesting if each new year version has the latest .NET.
     
    Last edited: Sep 23, 2022
  44. Adrian

    Adrian

    Joined:
    Apr 5, 2008
    Posts:
    1,066
    Maybe that's just a typo but the player runtime upgrade will be 2023.2 at the earliest, as Josh said they've missed the cutoff for 2023.1. That's also just for the player runtime, the editor runtime upgrade could well be a couple of Unity releases after that. And until the editor upgrade, using new .Net features will not really be practical for development. But Unity should track the latest .Net release pretty closely, so it could be .Net 8 or 9 when we're finally able to use it.
     
  45. runner78

    runner78

    Joined:
    Mar 14, 2015
    Posts:
    792
    Yes, it was a typo.
     
  46. rhke

    rhke

    Joined:
    Oct 5, 2022
    Posts:
    8
    Has anyone managed to get it to work?
    I still get:
    "Unable to resolve reference 'System.Text.Json'. Is the assembly missing or incompatible with the current platform?
    Reference validation can be disabled in the Plugin Inspector."
    Even after trying https://github.com/xoofx/UnityNuGet, maybe I've used it wrong but I'd like to ask if anyone managed to get it working after seeing this same error.
     
  47. h765643729

    h765643729

    Joined:
    Jan 17, 2018
    Posts:
    21
  48. Deleted User

    Deleted User

    Guest

    there are some hacks to get around this.

    The list just needs to be wrapped in an object. If you're receiving a raw list in the JSON, then you can do the following:

    Code (CSharp):
    1. const string listJson = @"[
    2.  1,
    3.  2,
    4.  3,
    5.  4,
    6. ]";
    7.  
    8. var wrappedListJson = $"{{\"value\":{listJson}}}";
    9. var wrappedList = JsonUtility.FromJson<Wrapped<List<int>>>(wrappedListJson);
    10. var list = wrappedList.value;
    11.  
    12. [System.Serializable]
    13. public struct Wrapped<T>
    14. {
    15.   public T value;
    16. }
    If you need to serialize the json to a list format, then you can use a substring.

    Code (CSharp):
    1. var list = new List<int>();
    2. list.Add(1);
    3. list.Add(2);
    4. list.Add(3);
    5. list.Add(4);
    6.  
    7. var wrappedList = new Wrapped<List<int>> { value = list };
    8. var wrappedListJson = JsonUtility.ToJson(wrappedList);
    9.  
    10. var prefixLength = "{\"value\":".Length;
    11. var postfixLength = "}".Length;
    12. var listLength = wrappedListJson.Length - prefixLength - postfixLength;
    13. var listJson =  wrappedListJson.Substring(prefixLength, listLength);
     
    Last edited by a moderator: Nov 11, 2022
    h765643729 likes this.
  49. Kamyker

    Kamyker

    Joined:
    May 14, 2013
    Posts:
    1,091
    Looks like a big waste of time just use Newtonsoft or system.text.json in Unity 2022.
     
    Deleted User likes this.
  50. Deleted User

    Deleted User

    Guest

    This is slightly related, but I'm curious. Would you prefer a unity-specific JSON library that is Burst-compatible to `System.Text.Json`?

    I'm not sure the usefulness of serializing/deserializing JSON in a Burst context, so I'd expect most people would prefer `System.Text.Json` as it's fast, easy enough, and the standard among .NET developers. When using JSON, you're interacting with web services, which aren't generally hot code paths. If you were using JSON in a performant context, you'd probably opt to use a better format anyway.