Insanely huge initial commit

This commit is contained in:
2026-02-21 17:04:05 -08:00
parent 9cdd36191a
commit 613d75914a
22525 changed files with 4035207 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9a21aefa9bf2b674e9e328b9198485ec
folderAsset: yes
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,416 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!29 &1
OcclusionCullingSettings:
m_ObjectHideFlags: 0
serializedVersion: 2
m_OcclusionBakeSettings:
smallestOccluder: 5
smallestHole: 0.25
backfaceThreshold: 100
m_SceneGUID: 00000000000000000000000000000000
m_OcclusionCullingData: {fileID: 0}
--- !u!104 &2
RenderSettings:
m_ObjectHideFlags: 0
serializedVersion: 9
m_Fog: 0
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
m_FogMode: 3
m_FogDensity: 0.01
m_LinearFogStart: 0
m_LinearFogEnd: 300
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
m_AmbientIntensity: 1
m_AmbientMode: 0
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3
m_HaloTexture: {fileID: 0}
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
m_DefaultReflectionMode: 0
m_DefaultReflectionResolution: 128
m_ReflectionBounces: 1
m_ReflectionIntensity: 1
m_CustomReflection: {fileID: 0}
m_Sun: {fileID: 0}
m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
m_UseRadianceAmbientProbe: 0
--- !u!157 &4
LightmapSettings:
m_ObjectHideFlags: 0
serializedVersion: 12
m_GIWorkflowMode: 0
m_GISettings:
serializedVersion: 2
m_BounceScale: 1
m_IndirectOutputScale: 1
m_AlbedoBoost: 1
m_EnvironmentLightingMode: 0
m_EnableBakedLightmaps: 1
m_EnableRealtimeLightmaps: 1
m_LightmapEditorSettings:
serializedVersion: 12
m_Resolution: 2
m_BakeResolution: 40
m_AtlasSize: 1024
m_AO: 0
m_AOMaxDistance: 1
m_CompAOExponent: 0
m_CompAOExponentDirect: 0
m_ExtractAmbientOcclusion: 0
m_Padding: 2
m_LightmapParameters: {fileID: 0}
m_LightmapsBakeMode: 1
m_TextureCompression: 1
m_FinalGather: 0
m_FinalGatherFiltering: 1
m_FinalGatherRayCount: 1024
m_ReflectionCompression: 2
m_MixedBakeMode: 1
m_BakeBackend: 0
m_PVRSampling: 1
m_PVRDirectSampleCount: 32
m_PVRSampleCount: 512
m_PVRBounces: 2
m_PVREnvironmentSampleCount: 512
m_PVREnvironmentReferencePointCount: 2048
m_PVRFilteringMode: 0
m_PVRDenoiserTypeDirect: 0
m_PVRDenoiserTypeIndirect: 0
m_PVRDenoiserTypeAO: 0
m_PVRFilterTypeDirect: 0
m_PVRFilterTypeIndirect: 0
m_PVRFilterTypeAO: 0
m_PVREnvironmentMIS: 0
m_PVRCulling: 1
m_PVRFilteringGaussRadiusDirect: 1
m_PVRFilteringGaussRadiusIndirect: 5
m_PVRFilteringGaussRadiusAO: 2
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
m_PVRFilteringAtrousPositionSigmaIndirect: 2
m_PVRFilteringAtrousPositionSigmaAO: 1
m_ExportTrainingData: 0
m_TrainingDataDestination: TrainingData
m_LightProbeSampleCountMultiplier: 4
m_LightingDataAsset: {fileID: 0}
m_LightingSettings: {fileID: 4890085278179872738, guid: 81af15b37c2dfd74a9fabf4dbb8a2827, type: 2}
--- !u!196 &5
NavMeshSettings:
serializedVersion: 2
m_ObjectHideFlags: 0
m_BuildSettings:
serializedVersion: 2
agentTypeID: 0
agentRadius: 0.5
agentHeight: 2
agentSlope: 45
agentClimb: 0.4
ledgeDropHeight: 0
maxJumpAcrossDistance: 0
minRegionArea: 2
manualCellSize: 0
cellSize: 0.16666667
manualTileSize: 0
tileSize: 256
accuratePlacement: 0
maxJobWorkers: 0
preserveTilesOutsideBounds: 0
debug:
m_Flags: 0
m_NavMeshData: {fileID: 0}
--- !u!1 &344286693
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 344286696}
- component: {fileID: 344286695}
- component: {fileID: 344286694}
m_Layer: 0
m_Name: Instructions Text
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!102 &344286694
TextMesh:
serializedVersion: 3
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 344286693}
m_Text: 'Nothing to see in this view.
When pressing Play, four example scripts
are executed.
Check their output from the console.
But mostly, see
the scripts themselves.
Additionally, you can see the debug window by choosing
Window
-> Total JSON -> JSON Runtime Debug
from Unity Editor menu.'
m_OffsetZ: 0
m_CharacterSize: 1
m_LineSpacing: 1
m_Anchor: 4
m_Alignment: 1
m_TabSize: 4
m_FontSize: 0
m_FontStyle: 0
m_RichText: 0
m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0}
m_Color:
serializedVersion: 2
rgba: 4294967295
--- !u!23 &344286695
MeshRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 344286693}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_StaticShadowCaster: 0
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_RayTracingMode: 2
m_RayTraceProcedural: 0
m_RenderingLayerMask: 1
m_RendererPriority: 0
m_Materials:
- {fileID: 10100, guid: 0000000000000000e000000000000000, type: 0}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_ReceiveGI: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 1
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_AdditionalVertexStreams: {fileID: 0}
--- !u!4 &344286696
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 344286693}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.3, y: 0.3, z: 0.3}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &479633131
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 479633135}
- component: {fileID: 479633134}
- component: {fileID: 479633133}
- component: {fileID: 479633132}
- component: {fileID: 479633136}
m_Layer: 0
m_Name: Attached Test Scripts
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &479633132
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 479633131}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 439d32b99b1777e4cb58c141cf204a68, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &479633133
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 479633131}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: d60680956f97c1a4c805c7d4dd9d5940, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!114 &479633134
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 479633131}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 45d8aa6e61f134c4d81a855552302b1e, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!4 &479633135
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 479633131}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &479633136
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 479633131}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: bccfa1f2b4b94074fad5e9bfd88c9430, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &1377886929
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1377886934}
- component: {fileID: 1377886933}
- component: {fileID: 1377886931}
- component: {fileID: 1377886930}
m_Layer: 0
m_Name: Main Camera
m_TagString: MainCamera
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!81 &1377886930
AudioListener:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1377886929}
m_Enabled: 1
--- !u!124 &1377886931
Behaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1377886929}
m_Enabled: 1
--- !u!20 &1377886933
Camera:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1377886929}
m_Enabled: 1
serializedVersion: 2
m_ClearFlags: 2
m_BackGroundColor: {r: 0, g: 0, b: 0, a: 0.019607844}
m_projectionMatrixMode: 1
m_GateFitMode: 2
m_FOVAxisMode: 0
m_SensorSize: {x: 36, y: 24}
m_LensShift: {x: 0, y: 0}
m_FocalLength: 50
m_NormalizedViewPortRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: 1
near clip plane: 5
far clip plane: 15
field of view: 60
orthographic: 1
orthographic size: 5
m_Depth: -1
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_RenderingPath: -1
m_TargetTexture: {fileID: 0}
m_TargetDisplay: 0
m_TargetEye: 3
m_HDR: 0
m_AllowMSAA: 1
m_AllowDynamicResolution: 0
m_ForceIntoRT: 0
m_OcclusionCulling: 1
m_StereoConvergence: 10
m_StereoSeparation: 0.022
--- !u!4 &1377886934
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1377886929}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: -10}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 0}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}

View File

@@ -0,0 +1,6 @@
fileFormatVersion: 2
guid: 85192120bb531ee4a887658f2f04b6f9
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,64 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!850595691 &4890085278179872738
LightingSettings:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: An_Example_SceneSettings
serializedVersion: 4
m_GIWorkflowMode: 0
m_EnableBakedLightmaps: 1
m_EnableRealtimeLightmaps: 1
m_RealtimeEnvironmentLighting: 1
m_BounceScale: 1
m_AlbedoBoost: 1
m_IndirectOutputScale: 1
m_UsingShadowmask: 0
m_BakeBackend: 0
m_LightmapMaxSize: 1024
m_BakeResolution: 40
m_Padding: 2
m_LightmapCompression: 3
m_AO: 0
m_AOMaxDistance: 1
m_CompAOExponent: 0
m_CompAOExponentDirect: 0
m_ExtractAO: 0
m_MixedBakeMode: 1
m_LightmapsBakeMode: 1
m_FilterMode: 1
m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0}
m_ExportTrainingData: 0
m_TrainingDataDestination: TrainingData
m_RealtimeResolution: 2
m_ForceWhiteAlbedo: 0
m_ForceUpdates: 0
m_FinalGather: 0
m_FinalGatherRayCount: 1024
m_FinalGatherFiltering: 1
m_PVRCulling: 1
m_PVRSampling: 1
m_PVRDirectSampleCount: 32
m_PVRSampleCount: 512
m_PVREnvironmentSampleCount: 512
m_PVREnvironmentReferencePointCount: 2048
m_LightProbeSampleCountMultiplier: 4
m_PVRBounces: 2
m_PVRMinBounces: 2
m_PVREnvironmentMIS: 0
m_PVRFilteringMode: 0
m_PVRDenoiserTypeDirect: 0
m_PVRDenoiserTypeIndirect: 0
m_PVRDenoiserTypeAO: 0
m_PVRFilterTypeDirect: 0
m_PVRFilterTypeIndirect: 0
m_PVRFilterTypeAO: 0
m_PVRFilteringGaussRadiusDirect: 1
m_PVRFilteringGaussRadiusIndirect: 5
m_PVRFilteringGaussRadiusAO: 2
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
m_PVRFilteringAtrousPositionSigmaIndirect: 2
m_PVRFilteringAtrousPositionSigmaAO: 1
m_PVRTiledBaking: 0

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 81af15b37c2dfd74a9fabf4dbb8a2827
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 4890085278179872738
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,131 @@
// Example - Create and modify JSON
using UnityEngine;
using System.Collections.Generic;
using Leguar.TotalJSON;
namespace Leguar.TotalJSON.Examples {
public class CreateAndModifyJSON : MonoBehaviour {
void Start() {
Debug.Log("---> Running CreateAndModifyJSON.Test1()");
Test1();
Debug.Log("---> Running CreateAndModifyJSON.Test2()");
Test2();
}
private void Test1() {
// Create empty JSON object "{}"
JSON jsonObject = new JSON();
// Add this JSON object to debug
// After this call, you can see content of this JSON object in Unity Editor, by choosing "Window -> Total JSON -> JSON Runtime Debug" from Unity menu
// For debug/development purposes it is very handy to see contents of JSON objects while application is running in editor
jsonObject.DebugInEditor("CreateAndModify Test JSON");
Debug.Log("Note! You can see the content of selected JSON objects while application is running by choosing \"Window -> Total JSON -> JSON Runtime Debug\" from Unity menu");
// Add basic things
jsonObject.Add("text","Hello World!");
jsonObject.Add("number",42);
jsonObject.Add("truth",true);
jsonObject.Add("nullText",null);
jsonObject.Add("numberArray",new int[]{1,2,4,8});
// Print out
Debug.Log(jsonObject.CreateString()); // {"text":"Hello World!","number":42,"truth":true,"nullText":null,"numberArray":[1,2,4,8]}
// Do some changes
jsonObject.Remove("number");
jsonObject.Replace("truth",false);
// Loop through all the keys and print out debug info of all values
Debug.Log("Info of all the values:");
foreach (string key in jsonObject.Keys) {
Debug.Log(key+": "+jsonObject[key]);
}
// Loop through all the keys and print out all values in JSON formatted strings
Debug.Log("Content of all the values:");
foreach (string key in jsonObject.Keys) {
Debug.Log(key+" -> "+jsonObject[key].CreateString());
}
// Get and print out some values
Debug.Log("Print outs of some values:");
Debug.Log(jsonObject.GetString("text")); // "Hello World!"
Debug.Log(jsonObject.ContainsKey("number")); // false
Debug.Log(jsonObject.GetBool("truth")); // false
Debug.Log(jsonObject.GetString("nullText")); // Null
// Do some changes to array
JArray jsonArray = jsonObject.GetJArray("numberArray"); // Contains ints 1,2,4,8
jsonArray.Add(16); // 1,2,4,8,16
jsonArray.RemoveAt(1); // 1,4,8,16
jsonArray.InsertAt(3,0); // 1,4,8,0,16
jsonArray.ReplaceAt(2,-1); // 1,4,-1,0,16
// Print out some array values
Debug.Log("Array length: "+jsonArray.Length); // 5
Debug.Log("Fifth element as int: "+jsonArray.GetInt(4)); // 16
// Since all values in array are numbers (JNumber) and they all fit to c# int values, array can be also copied to system int array
int[] systemIntArray = jsonArray.AsIntArray();
// Print out values
Debug.Log("Second element as int: "+systemIntArray[1]); // 4
}
private void Test2() {
// Create new JSON object from dictionary
Dictionary<string,object> dict = new Dictionary<string,object>();
dict.Add("one",1);
dict.Add("two",2f);
JSON jsonFromDict = new JSON(dict);
// Create new JSON array from list
List<string> list = new List<string>();
list.Add("ABC");
list.Add("XYZ");
list.Add("ijk");
JArray jArrayFromList = new JArray(list);
// Create number that would be outside c# supported integers, by creating new JSON number from string
JNumber bigInteger = new JNumber("184467440737095516150");
// Add them all to one JSON
JSON json = new JSON();
json.Add("fromDict",jsonFromDict);
json.Add("fromList",jArrayFromList);
json.Add("bigInteger",bigInteger);
// Print out in pretty form
Debug.Log("Human readable output:\n" + json.CreateString(new CreateStringSettings() { HumanReadable=true }));
/*
Prints out:
{
"fromDict": {
"one": 1,
"two": 2.0
},
"fromList": [
"ABC",
"XYZ",
"ijk"
],
"bigInteger": 184467440737095516150
}
*/
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 45d8aa6e61f134c4d81a855552302b1e
timeCreated: 1565518243
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 11
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 3cb709ed5db03f2479449dc02935cd74
folderAsset: yes
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,21 @@
// Example - Serialize and Deserialize - ExamplePlayerObject - ExamplePlayerItemObject
// This class is part of "SerializeAndDeserialize.cs" example code
using Leguar.TotalJSON;
namespace Leguar.TotalJSON.Examples {
public struct ExamplePlayerItemObject { // No particular reason for this to be 'struct' instead of 'class', just for the sake of different example
public string name;
public int uses;
public override string ToString() {
return "[ExamplePlayerItemObject: name = \""+name+"\", uses = "+uses+"]";
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: d9d112bdceb035647b1323e28992f074
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,112 @@
// Example - Serialize and Deserialize - ExamplePlayerObject
// This class is part of "SerializeAndDeserialize.cs" example code
using System;
using UnityEngine;
using System.Collections.Generic;
using Leguar.TotalJSON;
namespace Leguar.TotalJSON.Examples {
public class ExamplePlayerObject {
public string name;
public Vector3 position;
public Color playerColor;
private int sessionTime; // This field will not get serialized since it is 'private'
[SerializeField]
private int score; // This private field will be serialized since it is marked with [SerializeField]
[NonSerialized]
public int debugScore; // This public field will not be serialized since it is marked with [NonSerialized]
public float[] levelTimes;
public List<ExamplePlayerItemObject> playerBackPack;
public enum CharClass {
Fighter,
Mage,
Thief
}
public CharClass charClass;
public Dictionary<string,int> mapStates;
public bool? alignment; // Nullable boolean value to allow also "not set" state
public void SetTestValues() {
name = "Test player";
position = new Vector3(1f, 2f, 3f);
playerColor = new Color(0f, 1f, 0.1f, 0.9f);
sessionTime = 55555;
score = 42000;
debugScore = score;
levelTimes = new float[] { 31.41f, 42.0f, 12.3f };
playerBackPack = new List<ExamplePlayerItemObject>();
playerBackPack.Add(new ExamplePlayerItemObject() { name="axe", uses=99 });
playerBackPack.Add(new ExamplePlayerItemObject() { name="coin", uses=1 });
charClass = CharClass.Mage;
mapStates=new Dictionary<string, int>();
mapStates.Add("cave", 78);
mapStates.Add("lake", 42);
alignment = null;
}
public override string ToString() {
string str = "[ExamplePlayerObject: name = \""+name+"\", position = "+position+", playerColor = "+playerColor+", sessionTime = "+sessionTime+", score = "+score+", debugScore = "+debugScore+", levelTimes = ";
if (levelTimes!=null) {
str += '{';
for (int n = 0; n<levelTimes.Length; n++) {
str += levelTimes[n];
if (n<levelTimes.Length-1) {
str += ",";
}
}
str += '}';
} else {
str += "null";
}
str += ", playerBackPack = ";
if (playerBackPack!=null) {
str += '{';
for (int n = 0; n<playerBackPack.Count; n++) {
str += playerBackPack[n].ToString();
if (n<playerBackPack.Count-1) {
str += ',';
}
}
str += '}';
} else {
str += "null";
}
str += ", charClass = "+charClass+", mapStates = ";
if (mapStates!=null) {
str += '{';
bool first = true;
foreach (string key in mapStates.Keys) {
if (!first) {
str += ", ";
}
str += key+"="+mapStates[key];
first=false;
}
str += '}';
} else {
str += "null";
}
str += ", alignment = " + alignment + "]";
return str;
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: e8144ad3b5c903e48ae14310f239aed3
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,163 @@
// Example - Parse and handle JSON
using UnityEngine;
using Leguar.TotalJSON;
namespace Leguar.TotalJSON.Examples {
public class ParseAndHandleJSON : MonoBehaviour {
void Start() {
// Parsing Facebook user data
Debug.Log("---> Running ParseAndHandleJSON.ReadFBUserData()");
string dataFromFB = ReadFBUserData();
Debug.Log("---> Running ParseAndHandleJSON.ParseFBUserData()");
ParseFBUserData(dataFromFB);
// Parsing Google Play Store receipt data
Debug.Log("---> Running ParseAndHandleJSON.ReadGPSReceiptData()");
string dataFromGPS = ReadGPSReceiptData();
Debug.Log("---> Running ParseAndHandleJSON.ParseGPSReceiptData()");
ParseGPSReceiptData(dataFromGPS);
}
// Returns example JSON string that is in same format than real data received from Facebook would be when receiving player account info
private string ReadFBUserData() {
string dataFromFB = @"
{
""id"":""123456789012345"",
""name"":""Mumble Happyfeet"",
""first_name"":""Mumble"",
""last_name"":""Happyfeet"",
""picture"":{
""data"":{
""height"":50,
""width"":50,
""is_silhouette"":false,
""url"":""https://platform-lookaside.fbsbx.com/platform/profilepic/?asid=123456789012345&height=50&width=50&ext=1234567890&hash=AbCdeFghijkLmnop""
}
},
""email"":""not.exist@leguar.com"",
""gender"":""male"",
""birthday"":""02/02/1979"",
""location"":{
""location"":{
""city"":""Helsinki"",
""country"":""Finland"",
""latitude"":60.1708,
""longitude"":24.9375
},
""id"":""109876543210987""
},
""currency"":{
""currency_offset"":100,
""usd_exchange"":1.1534292,
""usd_exchange_inverse"":0.8669799585,
""user_currency"":""EUR""
}
}";
return dataFromFB;
}
private void ParseFBUserData(string jsonDataFromFbAsString) {
// Parse string data received from FB to JSON
// Second (optional) parameter is ID for debug purposes. If anything fails in JSON parsing, this debug id is added to exception message.
// This will greatly help tracking problems in projects where lots of JSON objects are handled and stack trace is not necessary available (like in production builds).
// This same debug id will be attached also to resulting JSON object so that if any exceptions happens afterwards (for example when reading values from JSON),
// thos eexceptions will have this ID printed out also.
JSON fbUserJSON = JSON.ParseString(jsonDataFromFbAsString,"FBUserJSON");
// Set JSON protected (read only) so no accidental changes are made to it
// In this example this is of course somewhat pointless since JSON is only used locally in this method and not passed forward to anywhere
// But very handy if this JSON is paased forward and you want to make sure no other code accidentally changes anything
fbUserJSON.SetProtected();
// Add this JSON object to runtime debug in Unity Editor
// After this call, you can see content of this JSON object in Unity Editor, by choosing "Window -> Total JSON -> JSON Runtime Debug" from Unity menu
fbUserJSON.DebugInEditor("FB User JSON");
// Get user basic info
string userId = fbUserJSON.GetString("id");
string name = fbUserJSON.GetString("name");
// Get user picture info
JSON userPictureData = fbUserJSON.GetJSON("picture").GetJSON("data");
bool isPictureSilhouette = userPictureData.GetBool("is_silhouette");
string pictureUrl = userPictureData.GetString("url");
// Get country
string country;
try {
// This code just assumes data contains location information, which it in real life doesn't necessary do
country = fbUserJSON.GetJSON("location").GetJSON("location").GetString("country");
}
catch (JSONKeyNotFoundException) { // The lazy way to handle possibly missing information
country = "Unknown";
}
// Get currency USD exchange
decimal? usdExchange = null;
if (fbUserJSON.ContainsKey("currency")) {
JSON userCurrency = fbUserJSON.GetJSON("currency");
usdExchange = userCurrency.GetJNumber("usd_exchange").AsDecimal();
}
// Print out what we got
Debug.Log("userId = "+userId);
Debug.Log("name = "+name);
Debug.Log("isPictureSilhouette = "+isPictureSilhouette);
Debug.Log("pictureUrl = "+pictureUrl);
Debug.Log("country = "+country);
Debug.Log("usdExchange = "+usdExchange);
}
// Returns example JSON string that is in same format than real data received from Google Play store would be when receiving purchase receipt
private string ReadGPSReceiptData() {
// Note that receipt really contains JSON that added inside other JSON's as strings, causing lots of escaping.
// Then the string is escaped once more here (using TotalJSON Validator included to this package) to make it compatible for adding it to c# source code.
string dataFromGPS="{\"Store\":\"GooglePlay\",\"TransactionID\":\"XYZ.1337-4242-1234-12345\",\"Payload\":\"{\\\"json\\\":\\\"{\\\\\\\"orderId\\\\\\\":\\\\\\\"XYZ.1337-4242-1234-12345\\\\\\\",\\\\\\\"packageName\\\\\\\":\\\\\\\"com.example.test\\\\\\\",\\\\\\\"productId\\\\\\\":\\\\\\\"niceProduct\\\\\\\",\\\\\\\"purchaseTime\\\\\\\":1504030209999,\\\\\\\"purchaseState\\\\\\\":0,\\\\\\\"purchaseToken\\\\\\\":\\\\\\\"abcdefghijklmno.AA-B1Cd--AbcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO\\\\\\\"}\\\",\\\"signature\\\":\\\"abcdefghijklmnopqrstuvwxyz\\\\/0123456789abcdefghijklmnopqrstuvwxyz+ETCetc==\\\"}\"}";
return dataFromGPS;
// Actual data without this last round of escaping here, looks like this:
// {"Store":"GooglePlay","TransactionID":"XYZ.1337-4242-1234-12345","Payload":"{\"json\":\"{\\\"orderId\\\":\\\"XYZ.1337-4242-1234-12345\\\",\\\"packageName\\\":\\\"com.example.test\\\",\\\"productId\\\":\\\"niceProduct\\\",\\\"purchaseTime\\\":1504030209999,\\\"purchaseState\\\":0,\\\"purchaseToken\\\":\\\"abcdefghijklmno.AA-B1Cd--AbcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNO\\\"}\",\"signature\":\"abcdefghijklmnopqrstuvwxyz\\/0123456789abcdefghijklmnopqrstuvwxyz+ETCetc==\"}"}
}
private void ParseGPSReceiptData(string jsonDataFromGpsAsString) {
// Parse string to JSON object
JSON jsonReceipt = JSON.ParseString(jsonDataFromGpsAsString);
Debug.Log("Store: "+jsonReceipt.GetString("Store"));
Debug.Log("TransactionID: "+jsonReceipt.GetString("TransactionID"));
// Parse payload to JSON object as it is saved as string to previous JSON object
JSON payloadAsJSON = JSON.ParseString(jsonReceipt.GetString("Payload"));
string signature = payloadAsJSON.GetString("signature");
Debug.Log("Signature: "+signature);
// One more round of parsing, as receipt is saved as string in previous JSON object
string receiptAsString = payloadAsJSON.GetString("json");
// In some cases there's no need to parse this string to JSON as some purchase validating backend exactly needs this receipt-json as string
// Just for sake of additional parsing example
JSON receiptAsJSON = JSON.ParseString(receiptAsString);
Debug.Log("packageName: "+receiptAsJSON.GetString("packageName"));
Debug.Log("purchaseTime: "+receiptAsJSON.GetJNumber("purchaseTime").AsLong());
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: d60680956f97c1a4c805c7d4dd9d5940
timeCreated: 1565518243
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 12
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,58 @@
// Example - Save and load JSON to/from text file
using UnityEngine;
using System.IO;
using Leguar.TotalJSON;
namespace Leguar.TotalJSON.Examples {
public class SaveAndLoadFile : MonoBehaviour {
// Note: Since this is just an example, file is saved to TotalJSON Examples folder!
// (Normally files should be saved to for example Application.persistentDataPath, depending on platform and what data is saved)
private const string FILE_PATH = "Assets/TotalJSON/Examples/Test_SaveFile.json";
void Start() {
Debug.Log("---> Running SaveAndLoadFile.Test()");
Test();
}
private void Test() {
// Create JSON object for testing
JSON originalObject = new JSON();
originalObject.Add("name", "Test Person");
originalObject.Add("age", 42);
// Save to text file
saveJsonObjectToTextFile(originalObject);
// Load from text file
JSON loadedObject = loadTextFileToJsonObject();
// Check that objects are equal
Debug.Log("Loaded object equals original object: "+loadedObject.Equals(originalObject));
}
private void saveJsonObjectToTextFile(JSON jsonObject) {
string jsonAsString = jsonObject.CreateString(); // Could also use "CreatePrettyString()" to make more human readable result, it is still valid JSON to read and parse by computer
StreamWriter writer = new StreamWriter(FILE_PATH);
writer.WriteLine(jsonAsString);
writer.Close();
}
private JSON loadTextFileToJsonObject() {
StreamReader reader = new StreamReader(FILE_PATH);
string jsonAsString = reader.ReadToEnd();
reader.Close();
JSON jsonObject = JSON.ParseString(jsonAsString);
return jsonObject;
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: bccfa1f2b4b94074fad5e9bfd88c9430
timeCreated: 1567109215
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 14
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,96 @@
// Example - Serialize and Deserialize
using UnityEngine;
using Leguar.TotalJSON;
namespace Leguar.TotalJSON.Examples {
public class SerializeAndDeserialize : MonoBehaviour {
void Start() {
Debug.Log("---> Running SerializeAndDeserialize.SerializePlayerObjectToString()");
string jsonString = SerializePlayerObjectToString();
Debug.Log("---> Running SerializeAndDeserialize.DeserializeStringToPlayerObject()");
DeserializeStringToPlayerObject(jsonString);
Debug.Log("---> Running SerializeAndDeserialize.SerAndDeserUnityStructs()");
SerAndDeserUnityStructs();
}
private string SerializePlayerObjectToString() {
// Create example player (c# object)
ExamplePlayerObject examplePlayer = new ExamplePlayerObject();
examplePlayer.SetTestValues();
// Print out current player data
Debug.Log("Original player: "+examplePlayer);
// Serialize ExamplePlayerObject to JSON object
JSON json = JSON.Serialize(examplePlayer);
// Output JSON
string jsonString = json.CreateString();
Debug.Log("Player as JSON for storing/transferring: " + jsonString);
// Content of 'jsonString' will be:
// {"name":"Test player","position":{"x":1.0,"y":2.0,"z":3.0},
// "playerColor":{"r":0.0,"g":1.0,"b":0.1,"a":0.9},"score":42000,
// "levelTimes":[31.41,42.0,12.3],"playerBackPack":[{"name":"axe","uses":99},{"name":"coin","uses":1}],
// "charClass":{"value__":1},"mapStates":{"cave":78,"lake":42},"alignment":null}
return jsonString;
}
private void DeserializeStringToPlayerObject(string jsonString) {
// Create JSON object from string
JSON json = JSON.ParseString(jsonString);
// Re-create ExamplePlayerObject from JSON
ExamplePlayerObject restoredPlayer = json.Deserialize<ExamplePlayerObject>();
// Print out
Debug.Log("Restored player: "+restoredPlayer);
}
private void SerAndDeserUnityStructs() {
// Create some basic Unity structs
Vector3 v3 = new Vector3(3f,14f,15f);
Quaternion q = new Quaternion(3f,3f,3f,4f);
Color32 c32 = new Color32(128,255,0,192);
Color c = new Color(0.5f,1f,0f,0.75f);
// Serialize them to JSON and store under one JSON object
JSON jsonObject = new JSON();
jsonObject.Add("v3",JSON.Serialize(v3));
jsonObject.Add("q",JSON.Serialize(q));
jsonObject.Add("c32",JSON.Serialize(c32));
jsonObject.Add("c",JSON.Serialize(c));
// Print out
Debug.Log("Structs stored to JSON: "+jsonObject.CreateString());
// Recreate (deserialize) structs from JSON
Vector3 vector3recreated = jsonObject.GetJSON("v3").Deserialize<Vector3>();
Quaternion quaternionRecreated = jsonObject.GetJSON("q").Deserialize<Quaternion>();
Color32 color32recreated = jsonObject.GetJSON("c32").Deserialize<Color32>();
Color colorRecreated = jsonObject.GetJSON("c").Deserialize<Color>();
// Print out
Debug.Log("Vector3 recreated: "+vector3recreated);
Debug.Log("Quaternion recreated: "+quaternionRecreated);
Debug.Log("Color32 recreated: "+color32recreated);
Debug.Log("Color recreated: "+colorRecreated);
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 439d32b99b1777e4cb58c141cf204a68
timeCreated: 1565518243
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 13
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 5f1e5077b7018ad42889478bca0fe3ef
folderAsset: yes
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,101 @@
// CreateStringRunner
using System;
using System.Text;
using UnityEngine;
namespace Leguar.TotalJSON.Internal {
class CreateStringRunner {
private CreateStringSettings settings;
private StringBuilder builder;
private string indentString;
private int currentIndent;
private string newLineString;
internal CreateStringRunner(CreateStringSettings settings) {
this.settings = settings;
builder=new StringBuilder();
if (settings.HumanReadable) {
if (settings.IndentUsingTab) {
indentString="\t";
} else {
indentString=new string(' ',settings.IndentSpaceCount);
}
currentIndent=0;
}
newLineString=getNewLineString();
}
internal void append(char chr) {
builder.Append(chr);
}
internal void append(char chr, bool space) {
builder.Append(chr);
if (space && settings.HumanReadable) {
builder.Append(' ');
}
}
internal void append(string str) {
builder.Append(str);
}
internal void append(char chr1, char chr2) {
builder.Append(chr1);
if (settings.HumanReadable) {
builder.Append(' ');
}
builder.Append(chr2);
}
internal void append(char chr, int indentChange) {
builder.Append(chr);
if (settings.HumanReadable) {
builder.Append(newLineString);
currentIndent += indentChange;
for (int n = 0; n<currentIndent; n++) {
builder.Append(indentString);
}
}
}
internal void append(int indentChange, char chr) {
if (settings.HumanReadable) {
builder.Append(newLineString);
currentIndent += indentChange;
for (int n = 0; n<currentIndent; n++) {
builder.Append(indentString);
}
}
builder.Append(chr);
}
internal bool isEscapeForwardSlashes() {
return settings.EscapeForwardSlashes;
}
internal string getFinalString() {
return builder.ToString();
}
private string getNewLineString() {
if (settings.NewLine==CreateStringSettings.NewLineTypes.EnvironmentDefault) {
return Environment.NewLine;
} else if (settings.NewLine==CreateStringSettings.NewLineTypes.LF) {
return "\n";
} else if (settings.NewLine==CreateStringSettings.NewLineTypes.CR_LF) {
return "\r\n";
} else {
Debug.LogError("Leguar.TotalJSON: CreateStringRunner.getNewLine(): Internal error: Unspecified new line type");
return Environment.NewLine;
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 69184000601c75749b791c0d9be41e44
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 9f2fdab21a6aeaf41956a4d04ddf4dd2
folderAsset: yes
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,204 @@
// JSONRuntimeDebug
using UnityEngine;
using UnityEditor;
using System.Collections.Generic;
namespace Leguar.TotalJSON.Internal {
public class JSONRuntimeDebug : EditorWindow {
private static int selected=0;
private static List<DebugObject> latestObjects;
private static bool previousWasPlaying = false;
[MenuItem("Window/Total JSON/JSON Runtime Debug")]
static void Init() {
JSONRuntimeDebug window=(JSONRuntimeDebug)(GetWindow(typeof(JSONRuntimeDebug)));
#if UNITY_5 || UNITY_2017
window.titleContent = new GUIContent("JSON Runtime Debug");
#else
Texture2D icon = (Texture2D)(AssetDatabase.LoadAssetAtPath("Assets/TotalJSON/Internal/Editor/window-icon.png", typeof(Texture2D)));
window.titleContent = new GUIContent("JSON Runtime Debug",icon);
#endif
}
void OnGUI() {
GUILayout.Space(15);
if (!Application.isPlaying) {
if (latestObjects==null) {
GUILayout.Label("Application is not running. This debug is available only when application is running and some JSON/Jarray object is added to debug.");
} else {
GUILayout.Label("Application is not running. Below is last state of JSON/Jarray objects from previous run.");
if (previousWasPlaying) {
foreach (DebugObject latestObject in latestObjects) {
latestObject.refresh();
}
}
outputLatestContent();
}
previousWasPlaying=false;
return;
} else {
previousWasPlaying=true;
}
JSONRuntimeDebugContainer jsonRuntimeDebugContainer=null;
GameObject jsonDebugObject=GameObject.Find("TotalJSON_DebugObject");
if (jsonDebugObject!=null) {
jsonRuntimeDebugContainer=jsonDebugObject.GetComponent<JSONRuntimeDebugContainer>();
}
if (jsonRuntimeDebugContainer==null) {
GUILayout.Label("Application is running but no JSON objects are added to debug.");
latestObjects=null;
return;
}
GUILayout.Label("Application is running, choose object below to show.");
if (latestObjects==null) {
latestObjects=new List<DebugObject>();
}
Dictionary<string,JValue> currentContent=jsonRuntimeDebugContainer.getContent();
foreach (string key in currentContent.Keys) {
int listIndex=getDebugObjectIndex(key);
if (listIndex>=0) {
if (latestObjects[listIndex].getValue()!=currentContent[key]) {
latestObjects[listIndex].replace(currentContent[key]);
}
} else {
latestObjects.Add(new DebugObject(key,currentContent[key]));
}
}
outputLatestContent();
}
private int getDebugObjectIndex(string key) {
for (int n=0; n<latestObjects.Count; n++) {
if (latestObjects[n].getKey().Equals(key)) {
return n;
}
}
return -1;
}
private void outputLatestContent() {
GUILayout.Space(10);
int count=latestObjects.Count;
string[] keys=new string[latestObjects.Count];
for (int n=0; n<count; n++) {
keys[n]=latestObjects[n].getKey();
}
int newSelected=GUILayout.Toolbar(selected,keys);
if (newSelected!=selected) {
selected=newSelected;
GUIUtility.keyboardControl=0;
GUIUtility.hotControl=0;
}
GUILayout.Space(10);
EditorGUILayout.BeginHorizontal();
GUILayout.Label(latestObjects[selected].getInfoString());
if (Application.isPlaying) {
GUILayout.FlexibleSpace();
if (GUILayout.Button("Refresh")) {
latestObjects[selected].refresh();
Repaint();
}
}
EditorGUILayout.EndHorizontal();
GUILayout.Space(5);
latestObjects[selected].scrollPos = EditorGUILayout.BeginScrollView(latestObjects[selected].scrollPos);
EditorGUILayout.TextArea(latestObjects[selected].getContentString(),GUILayout.ExpandHeight(true));
EditorGUILayout.EndScrollView();
}
private class DebugObject {
private string key;
private JValue value;
internal Vector2 scrollPos;
private string infoString;
private string contentString;
internal DebugObject(string key, JValue value) {
this.key=key;
this.value=value;
refresh();
}
internal void replace(JValue value) {
this.value=value;
refresh();
}
internal void refresh() {
scrollPos=Vector2.zero;
infoString=null;
contentString=null;
}
internal string getKey() {
return key;
}
internal JValue getValue() {
return value;
}
internal string getInfoString() {
if (infoString==null) {
infoString=value.ToString();
if (isProtected()) {
infoString+=" -- This object is set protected (read only)";
}
}
return infoString;
}
internal string getContentString() {
if (contentString==null) {
contentString=value.CreateString(new CreateStringSettings() { HumanReadable=true });
}
return contentString;
}
private bool isProtected() {
if (value is JSON) {
return ((JSON)(value)).IsProtected();
}
if (value is JArray) {
return ((JArray)(value)).IsProtected();
}
return false;
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: dd472f7a2d8907c4fa13cc27c68a39f4
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,192 @@
// JSONValidator
using UnityEngine;
using UnityEditor;
using System;
using System.Text;
using Leguar.TotalJSON;
namespace Leguar.TotalJSON.Internal {
public class JSONValidator : EditorWindow {
private string editorAreaText="Write or copy&paste JSON object or JSON array to this text area. Example JSON:\n\n{\"name\":\"Player\",\"lastLogin\":123456789012,\"achievements\":[42,1337,1703],\"imageUrl\":null,\"have_bought\":true,\"levels\":[{\"passed\":true,\"score\":12345},{\"passed\":false}]}\n\nExtra texts like this before or after JSON object will be removed when clicking button below.";
private string message="";
private string tightJSON="";
private string escapedJSON="";
private Vector2 scrollPos;
private float lineHeight=EditorGUIUtility.singleLineHeight;
[MenuItem("Window/Total JSON/JSON Validator")]
static void Init() {
JSONValidator window=(JSONValidator)(GetWindow(typeof(JSONValidator)));
#if UNITY_5 || UNITY_2017
window.titleContent = new GUIContent("JSON Validator");
#else
Texture2D icon = (Texture2D)(AssetDatabase.LoadAssetAtPath("Assets/TotalJSON/Internal/Editor/window-icon.png", typeof(Texture2D)));
window.titleContent = new GUIContent("JSON Validator",icon);
#endif
}
void OnGUI() {
GUILayout.Space(20);
scrollPos = EditorGUILayout.BeginScrollView(scrollPos);
EditorGUI.BeginChangeCheck();
editorAreaText = EditorGUILayout.TextArea(editorAreaText,GUILayout.ExpandHeight(true));
bool changes = EditorGUI.EndChangeCheck();
EditorGUILayout.EndScrollView();
if (changes) {
message = "";
tightJSON = "";
escapedJSON = "";
}
GUILayout.Space(10);
if (GUILayout.Button("Trim, validate and prettify above JSON object or array")) {
string trimmedEditorText=editorAreaText.Trim();
if (trimmedEditorText.Length<editorAreaText.Length) {
editorAreaText=trimmedEditorText; // Needed in case of errors, so that line numbers will match
GUIUtility.keyboardControl=0;
GUIUtility.hotControl=0;
EditorUtility.SetDirty(this);
}
if (string.IsNullOrEmpty(trimmedEditorText)) {
message = "Input is empty";
tightJSON = "";
escapedJSON = "";
} else {
object objectOrError = findAndGetJSONOrJArray(trimmedEditorText);
if (objectOrError==null) {
message = "Can't find JSON start from input";
tightJSON = "";
escapedJSON = "";
} else if (objectOrError is string) {
message = "Invalid input: "+((string)(objectOrError));
tightJSON = "";
escapedJSON = "";
} else {
CreateStringSettings prettySettings=new CreateStringSettings() {
HumanReadable=true,
IndentUsingTab=true,
NewLine=CreateStringSettings.NewLineTypes.LF // \r characters (may be part of environment default) seem to be problem in editor textarea, causing invisible linefeeds, so using plain \n
};
if (objectOrError is JSON[]) {
JSON[] jsons = (JSON[])(objectOrError);
if (jsons.Length==1) {
message = "JSON is valid. Top level JSON key/value pair count = "+jsons[0].Count;
editorAreaText = jsons[0].CreateString(prettySettings)+"\n";
tightJSON = jsons[0].CreateString(new CreateStringSettings() { HumanReadable = false });
escapedJSON = "\""+getEscapedString(tightJSON)+"\"";
} else {
message = "JSONs are valid. JSON object count = "+jsons.Length;
editorAreaText = "";
tightJSON = "";
for (int n = 0; n<jsons.Length; n++) {
editorAreaText += jsons[n].CreateString(prettySettings)+"\n";
if (n<jsons.Length-1) {
editorAreaText += '\n';
}
tightJSON += jsons[n].CreateString(new CreateStringSettings() { HumanReadable = false });
}
escapedJSON = "\""+getEscapedString(tightJSON)+"\"";
}
} else {
JArray jArray = (JArray)(objectOrError);
message = "JSON Array is valid. Top level array length = "+jArray.Length;
editorAreaText = jArray.CreateString(prettySettings)+"\n";
tightJSON = jArray.CreateString(new CreateStringSettings() { HumanReadable = false });
escapedJSON = "\""+getEscapedString(tightJSON)+"\"";
}
GUIUtility.keyboardControl=0;
GUIUtility.hotControl=0;
EditorUtility.SetDirty(this);
}
}
}
GUILayout.Space(20);
GUILayout.Label(message);
GUILayout.Space(20);
EditorGUI.BeginDisabledGroup(tightJSON.Length==0);
GUILayout.Label("JSON formatted and encoded string ("+tightJSON.Length+" bytes):");
GUILayout.Space(5);
EditorGUILayout.SelectableLabel(tightJSON,EditorStyles.textField,GUILayout.Height(lineHeight+2));
GUILayout.Space(15);
GUILayout.Label("Above string with escapes (to be used for example directly in c# source code):");
GUILayout.Space(5);
EditorGUILayout.SelectableLabel(escapedJSON,EditorStyles.textField,GUILayout.Height(lineHeight+2));
GUILayout.Space(20);
EditorGUI.EndDisabledGroup();
}
private object findAndGetJSONOrJArray(string dirtySourceString) {
// Remove any heading "trash", for example in case that JSON is pasted from Unity Console
int jsonStartIndex=dirtySourceString.IndexOf('{');
int jArrayStartIndex=dirtySourceString.IndexOf('[');
// Debug.Log("jsonStartIndex = "+jsonStartIndex);
// Debug.Log("jArrayStartIndex = "+jArrayStartIndex);
// Nothing?
if (jsonStartIndex<0 && jArrayStartIndex<0) {
return null;
}
// Try parse array
if (jArrayStartIndex>=0 && (jArrayStartIndex<jsonStartIndex || jsonStartIndex<0)) {
try {
return JArray.ParseString(dirtySourceString,new ParseStringSettings(){ ParseStartIndex=jArrayStartIndex, AllowNonWhiteCharactersAfterObject=true });
}
catch (ParseException e) {
if (jsonStartIndex<0) {
return e.Message;
}
}
}
// Parse one or more JSONs
try {
return JSON.ParseStringToMultiple(dirtySourceString,new ParseStringSettings(){ ParseStartIndex=jsonStartIndex, AllowNonWhiteCharactersAfterObject=true });
}
catch (ParseException e) {
return e.Message;
}
}
private static string getEscapedString(string source) {
int length=source.Length;
StringBuilder sb=new StringBuilder(length);
for (int n=0; n<length; n++) {
if (source[n]=='"') {
sb.Append('\\');
sb.Append('"');
} else if (source[n]=='\\') {
sb.Append('\\');
sb.Append('\\');
} else {
sb.Append(source[n]);
}
}
return sb.ToString();
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 9a3e3d053758ae04d8a800e805da99ba
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 271 B

View File

@@ -0,0 +1,123 @@
fileFormatVersion: 2
guid: 7de077ad9b723ed40b5ae6d8a8320274
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMasterTextureLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: -3
maxTextureSize: 32
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 16
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 1
cookieLightType: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 32
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 32
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 32
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 0
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
spritePackingTag:
pSDRemoveMatte: 0
pSDShowRemoveMatteOption: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,353 @@
// InternalTools
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
#if UNITY_EDITOR
using UnityEngine;
#endif
namespace Leguar.TotalJSON.Internal {
class InternalTools {
internal static JValue objectAsJValue(object value) {
List<object> stack = new List<object>();
return objectAsJValue(value, stack);
}
private static JValue objectAsJValue(object value, List<object> stack) {
// Single object?
JValue jValue=singleObjectAsJValue(value);
if (jValue!=null) {
return jValue;
}
// Dictionary
if (value is IDictionary) {
return dictionaryToJSON((IDictionary)(value), new JSON(), stack);
}
// List/array
if (value is IList) {
return listToJArray((IList)(value), new JArray(), stack);
}
// Unknown, handled by caller
return null;
}
internal static JSON dictionaryToJSON(IDictionary sourceDictionary, JSON targetJSON, List<object> stack) {
stack.Add(sourceDictionary);
foreach (object objectKey in sourceDictionary.Keys) {
if (objectKey==null) { // Dictionary can't have null keys though because calculating hash wouldn't work? No harm to check anyway
throw (new JArgumentException("Dictionary 'key' can not be null", "sourceDictionary"));
}
if (!(objectKey is string)) {
throw (new JArgumentException("Key have to be string in JSON.<init>(IDictionary) constructor", "sourceDictionary"));
}
string stringKey = (string)(objectKey);
object objectValue = sourceDictionary[objectKey];
if (stack.Contains(objectValue)) {
throw (new JArgumentException("Dictionary value is referring to earlier object. This would cause circular JSON.", "sourceDictionary[\""+stringKey+"\"]"));
}
JValue jValue = InternalTools.objectAsJValue(objectValue, stack);
if (jValue==null) {
throw (new UnknownObjectTypeException(objectValue, "sourceDictionary[\""+stringKey+"\"]"));
}
targetJSON.Add(stringKey, jValue);
}
stack.Remove(sourceDictionary);
return targetJSON;
}
internal static JArray listToJArray(IList sourceList, JArray targetJArray, List<object> stack) {
stack.Add(sourceList);
for (int n = 0; n<sourceList.Count; n++) {
object listItem = sourceList[n];
if (stack.Contains(listItem)) {
throw (new JArgumentException("List item is referring to earlier object. This would cause circular JSON.", "sourceList["+n+"]"));
}
JValue jValue = InternalTools.objectAsJValue(listItem, stack);
if (jValue==null) {
throw (new UnknownObjectTypeException(listItem, "sourceList["+n+"]"));
}
targetJArray.Add(jValue);
}
stack.Remove(sourceList);
return targetJArray;
}
internal static JValue serializeObject(object obj, SerializeSettings serializeSettings) {
List<object> stack = new List<object>();
return serializeObject(obj, serializeSettings, stack);
}
// This never returns null
private static JValue serializeObject(object obj, SerializeSettings serializeSettings, List<object> stack) {
JValue singleValue=singleObjectAsJValue(obj);
if (singleValue!=null) {
return singleValue;
}
if (obj is IList) {
JArray jArray = new JArray();
IList list = (IList)(obj);
stack.Add(obj);
for (int n=0; n<list.Count; n++) {
object listItem = list[n];
if (stack.Contains(listItem)) {
throw (new SerializeException("List item is referring to earlier object. This would cause circular JSON.", listItem));
}
JValue jValue=serializeObject(listItem, serializeSettings, stack);
if (jValue==null) {
throw (new SerializeException("List item is type that can't be serialized", listItem));
}
jArray.Add(jValue);
}
stack.Remove(obj);
return jArray;
}
Type type = obj.GetType();
if (type.IsGenericType) {
if (type.GetGenericTypeDefinition()==typeof(Dictionary<,>)) {
JSON json = new JSON();
Type[] dictTypes = type.GetGenericArguments();
bool dictKeyIsString = (dictTypes[0]==typeof(string));
if (!serializeSettings.AllowNonStringDictionaryKeys && !dictKeyIsString) {
throw (new SerializeException("Dictionary key is type ('"+dictTypes[0]+"') that can't be serialized. Dictionary keys must be strings, or allow more loose options using SerializeSettings"));
}
IDictionary dict = (IDictionary)(obj);
stack.Add(obj);
foreach (object objectKey in dict.Keys) {
object dictionaryValue = dict[objectKey];
if (stack.Contains(dictionaryValue)) {
throw (new SerializeException("Dictionary value is referring to earlier object. This would cause circular JSON.", dictionaryValue));
}
JValue jValue = serializeObject(dictionaryValue, serializeSettings, stack);
if (jValue==null) {
throw (new SerializeException("Dictionary item is type that can't be serialized", dictionaryValue));
}
string stringKey;
if (dictKeyIsString) {
stringKey = (string)(objectKey);
} else {
stringKey = objectKey.ToString();
}
json.Add(stringKey, jValue);
}
stack.Remove(obj);
return json;
}
}
JSON jsonSer = new JSON();
FieldInfo[] fieldInfos = obj.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
stack.Add(obj);
foreach (FieldInfo fieldInfo in fieldInfos) {
if (isSerializing(fieldInfo, serializeSettings.IgnoreSystemAndUnitySerializeAttributes)) {
string fieldName = fieldInfo.Name;
object fieldToSerialize = fieldInfo.GetValue(obj);
if (stack.Contains(fieldToSerialize)) {
throw (new SerializeException("Class field is referring to earlier object. This would cause circular JSON.", fieldToSerialize));
}
JValue jValue = serializeObject(fieldToSerialize, serializeSettings, stack);
if (jValue==null) {
throw (new SerializeException("Field \""+fieldName+"\" is type that can't be serialized",fieldToSerialize));
}
jsonSer.Add(fieldName,jValue);
}
}
stack.Remove(obj);
return jsonSer;
}
internal static bool isSerializing(FieldInfo fieldInfo, bool ignoreNonJSONSpecificAttributes) {
object[] attributes = fieldInfo.GetCustomAttributes(false);
if (containsType(attributes,typeof(ExcludeFromJSONSerializeAttribute))) {
return false;
}
if (!ignoreNonJSONSpecificAttributes) {
if (containsType(attributes,typeof(System.NonSerializedAttribute))) {
return false;
}
}
if (fieldInfo.IsPublic && !fieldInfo.IsLiteral) {
return true;
}
if (containsType(attributes,typeof(IncludeToJSONSerializeAttribute))) {
return true;
}
if (!ignoreNonJSONSpecificAttributes) {
if (containsType(attributes,typeof(UnityEngine.SerializeField))) {
return true;
}
}
return false;
}
private static bool containsType(object[] attributes, Type type) {
foreach (object attribute in attributes) {
if (attribute.GetType()==type) {
return true;
}
}
return false;
}
private static JValue singleObjectAsJValue(object value) {
// Null
if (value==null) {
return (new JNull());
}
// JValue directly
if (value is JValue) {
return ((JValue)(value));
}
// Known numbers
if (value is float) {
return (new JNumber((float)(value)));
}
if (value is double) {
return (new JNumber((double)(value)));
}
if (value is decimal) {
return (new JNumber((decimal)(value)));
}
if (value is byte) {
return (new JNumber((byte)(value)));
}
if (value is sbyte) {
return (new JNumber((sbyte)(value)));
}
if (value is short) {
return (new JNumber((short)(value)));
}
if (value is ushort) {
return (new JNumber((ushort)(value)));
}
if (value is int) {
return (new JNumber((int)(value)));
}
if (value is uint) {
return (new JNumber((uint)(value)));
}
if (value is long) {
return (new JNumber((long)(value)));
}
if (value is ulong) {
return (new JNumber(((ulong)(value)).ToString(CultureInfo.InvariantCulture)));
}
// String
if (value is string) {
return (new JString((string)(value)));
}
// Bool
if (value is bool) {
return (new JBoolean((bool)(value)));
}
// Unknown, handled by caller
return null;
}
internal static object jValueAsSystemObject(JValue jValue) {
if (jValue is JSON) {
return ((JSON)(jValue)).AsDictionary();
} else if (jValue is JArray) {
return ((JArray)(jValue)).AsList();
} else if (jValue is JNumber) {
return ((JNumber)(jValue)).AsObject();
} else if (jValue is JString) {
return ((JString)(jValue)).AsString();
} else if (jValue is JBoolean) {
return ((JBoolean)(jValue)).AsBool();
} else { // JNull
return null;
}
}
internal static string getExceptionMessageTailForID(string debugIDForExceptions, string exceptionSource) {
if (debugIDForExceptions!=null) {
return (" - "+exceptionSource+" Debug ID: \""+debugIDForExceptions+"\"");
}
return "";
}
internal static string getCleanedStackTrace(string originalStackTrace) {
string cleanedStackTrace=originalStackTrace;
bool first=true;
do {
int lf=getLineFeedIndex(cleanedStackTrace);
if (lf<=0) {
if (first) {
// This is unexpected, just returning original stacktrace as fallback
return originalStackTrace;
} else {
return cleanedStackTrace;
}
}
first=false;
if (!isInternalStackTraceLine(cleanedStackTrace.Substring(0,lf))) {
return cleanedStackTrace;
}
cleanedStackTrace=cleanedStackTrace.Substring(lf+1);
} while (true);
}
private static int getLineFeedIndex(string source) {
int i=source.IndexOf('\n');
return i;
}
private static bool isInternalStackTraceLine(string str) {
int packegeName=str.IndexOf("Leguar.TotalJSON.");
if (packegeName<0) {
return false;
}
int i1=str.IndexOf('(');
if (i1>0 && i1<packegeName) {
return false;
}
int i2=str.IndexOf('<');
if (i2>0 && i2<packegeName) {
return false;
}
return true;
}
#if UNITY_EDITOR
internal static JSONRuntimeDebugContainer getDebugContainer() {
GameObject jsonDebugObject = GameObject.Find("TotalJSON_DebugObject");
if (jsonDebugObject==null) {
jsonDebugObject=new GameObject("TotalJSON_DebugObject");
jsonDebugObject.hideFlags=HideFlags.HideInHierarchy;
GameObject.DontDestroyOnLoad(jsonDebugObject);
}
JSONRuntimeDebugContainer jsonRuntimeDebugContainer = jsonDebugObject.GetComponent<JSONRuntimeDebugContainer>();
if (jsonRuntimeDebugContainer==null) {
jsonRuntimeDebugContainer=jsonDebugObject.AddComponent<JSONRuntimeDebugContainer>();
}
return jsonRuntimeDebugContainer;
}
#endif
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 0993856fabc941a488b888d8a2c47eeb
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,40 @@
// TotalJSON - JSONRuntimeDebugContainer
#if UNITY_EDITOR
using UnityEngine;
using System.Collections.Generic;
namespace Leguar.TotalJSON.Internal {
public class JSONRuntimeDebugContainer : MonoBehaviour {
private Dictionary<string,JValue> content;
internal JSONRuntimeDebugContainer() {
content=new Dictionary<string, JValue>();
}
internal void add(string debugName, JValue jValue) {
foreach (string key in content.Keys) {
if (content[key]==jValue) {
if (key.Equals(debugName)) {
return; // Adding same object with same name, all done
}
content.Remove(key); // Remove previous one so that same object is not in debug twice (but this allows "changing name" of debugged object)
break;
}
}
content[debugName]=jValue;
}
public Dictionary<string, JValue> getContent() {
return content;
}
}
}
#endif

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 13a924cf4cad1d74197dc64bf37f9ca7
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,75 @@
// ParseStringRunner
namespace Leguar.TotalJSON.Internal {
class ParseStringRunner {
private ParseStringSettings settings;
private StringPointer stringPointer;
internal ParseStringRunner(string sourceString, ParseStringSettings settings) {
if (settings==null) {
settings = new ParseStringSettings();
}
this.settings = settings;
stringPointer=new StringPointer(sourceString,settings.ParseStartIndex,this);
}
internal StringPointer getStringPointer() {
return stringPointer;
}
internal bool containsNonWhiteChars() {
return stringPointer.containsNonWhiteChars();
}
internal string getPossiblyFixedNumber(string originalNumber) {
if (settings.FixRoundedFloatingPointMinMaxValues) {
string testNumber = originalNumber.Replace('e','E');
if (testNumber.Equals("3.402823E+38")) { // Rounded float.MaxValue
return "3.40282347E+38"; // Exact float.MaxValue
}
if (testNumber.Equals("-3.402823E+38")) { // Rounded float.MinValue
return "-3.40282347E+38"; // Exact float.MinValue
}
if (testNumber.Equals("1.79769313486232E+308")) { // Rounded double.MaxValue
return "1.7976931348623157E+308"; // Exact double.MaxValue (that doesn't throw OverflowException if read as double)
}
if (testNumber.Equals("-1.79769313486232E+308")) { // Rounded double.MinValue
return "-1.7976931348623157E+308"; // Exact double.MinValue (that doesn't throw OverflowException if read as double)
}
}
return originalNumber;
}
internal bool isAllowNonWhiteCharactersAfterObject() {
return settings.AllowNonWhiteCharactersAfterObject;
}
internal JValue parseValue() {
char chr=stringPointer.getNextNonWhiteChar();
if (chr=='"') {
return JString.zParse(this,false);
} else if (chr=='-' || (chr>='0' && chr<='9')) {
return JNumber.zParse(this,chr);
} else if (chr=='{') {
return JSON.zParse(this,false,false,false);
} else if (chr=='[') {
return JArray.zParse(this,false);
} else if (chr=='t' || chr=='f') {
return JBoolean.zParse(this,(chr=='t'));
} else if (chr=='n') {
return JNull.zParse(this);
} else {
throw ParseException.forInvalidCharacter("Invalid character '"+chr+"' when expecting start of any value",this);
}
}
internal string getParseDebugIDForExceptions() {
return settings.DebugIDForExceptions;
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 5eed20d76b51c3046ac7d57011b161d7
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,144 @@
// StringPointer
using System.Text;
namespace Leguar.TotalJSON.Internal {
class StringPointer {
private string str;
private int strLength;
private int nextChar;
// For debugging
private ParseStringRunner psrForDebug;
private char lastChr;
private int line;
private int col;
// For stepping back
private char sbLastChr;
private int sbLine;
private int sbCol;
// internal StringPointer(string str) : this(str,0) {
// }
internal StringPointer(string str, int startIndex, ParseStringRunner psrForDebug) {
this.str=str;
strLength=str.Length;
nextChar=startIndex;
this.psrForDebug = psrForDebug;
lastChr='\0';
line=1;
col=0;
}
internal bool containsNonWhiteChars() {
foreach (char chr in str) {
if (!isWhiteChar(chr)) {
return true;
}
}
return false;
}
internal bool tryGetNextNonWhiteChar(out char chr) {
do {
if (nextChar>=strLength) {
chr=default(char);
return false;
}
chr=getNextChar();
} while (isWhiteChar(chr));
return true;
}
internal char getNextNonWhiteChar() {
char chr;
do {
chr=getNextChar();
} while (isWhiteChar(chr));
return chr;
}
internal char getNextChar() {
if (nextChar>=strLength) {
throw ParseException.forInvalidEnd(psrForDebug);
}
sbLastChr=lastChr;
sbLine=line;
sbCol=col;
char chr=str[nextChar];
nextChar++;
if (chr=='\n' || chr=='\r') {
if ((chr=='\n' && lastChr!='\r') || (chr=='\r' && lastChr!='\n')) {
line++;
col=0;
}
} else {
col++;
}
lastChr=chr;
return chr;
}
internal bool isNextChars(string sequence) {
foreach (char chr in sequence) {
if (getNextChar()!=chr) {
return false;
}
}
return true;
}
internal int getCurrentIndex() {
return nextChar;
}
internal void stepBack() {
nextChar--;
lastChr=sbLastChr;
line=sbLine;
col=sbCol;
}
internal string getSubStringStartingFrom(int start) {
return str.Substring(start,nextChar-start);
}
internal string getLineAndColumnForException() {
return ("line "+line+", col "+col);
}
internal string getSubStringForException(int count) {
int start=nextChar-count;
if (start<0) {
count+=start;
start=0;
}
if (start+count>strLength) {
count=strLength-start;
}
if (count==0) {
return "";
}
StringBuilder sb=new StringBuilder();
if (start>0) {
sb.Append("...");
}
sb.Append(str.Substring(start,count));
if (start+count<strLength) {
sb.Append("...");
}
return sb.ToString();
}
private bool isWhiteChar(char chr) {
return (chr==' ' || chr=='\t' || chr=='\n' || chr=='\r');
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 2077e5258f6b9ce43be7c1406c16aa4f
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,268 @@
========================
TotalJSON - ReadMe.txt
========================
JSON
====
If you are not familiar of JSON format itself, check out http://json.org/ first.
Basic usage
===========
This package is nothing but C# code (excluding one example scene). All the public scripts
are in folder TotalJSON/Scripts/
Take these in use in your own code:
using Leguar.TotalJSON;
Classes represeting JSON objects and values are:
* JSON - Main JSON object class where data is saved as key/value pairs
* JArray - JSON array where data is accessed by index
* JString - String value
* JNumber - Number value (integer or floating point number)
* JBoolean - Boolean (bool) value
* JNull - JSON null value
Scripts folder also contains JValue, which is just abstract base class for all above classes
and is usually not used directly.
JSON and JArray are different from others in sense that they can be modified after instance
is created. You can use provided methods to add, remove and replace values in them.
Creating and modifying
----------------------
You can create new JSON object
JSON json = new JSON();
and use provided method to add/modify/remove data.
Arrays can be created similarly
JArray jArray = new JArray();
Typically values are added to JSON or JArray objects directly like
json.Add("answer",42);
or
jArray.Add(true);
All the Add, Replace, Insert etc methods accepts 'object' as input parameter. This
object can be anything that can be converted to some JValue object without any ambiguity.
For example strings, any C# number types, booleans and null. Obviously other JSON objects
or JArray arrays are fine too.
But JSON-number, -string, -boolean and -null values can be created separately
JNumber jsonNumber = new JNumber(42);
and then be added to JSON or JArray objects.
This is useful especially with numbers that would go outside normal C# number range:
json.Add("huge_integer",new JNumber("123456789012345678901234567890"));
or
jArray.InsertAt(0,new JNumber("3.1415E+42000"));
Parsing and creating JSON formatted strings
-------------------------------------------
Strings that are in JSON format like
{"name":"Pingu","active":true,"items":[1,2,4]}
can be turned to JSON object using static method
JSON json = JSON.ParseString(inputString);
Likewise, JSON object can be turned to JSON-formatted string using
string outputString = json.CreateString();
usually for storing or sending to another system.
There's also method to get JSON out in more human friendly format using
Debug.Log(json.CreatePrettyString());
typically for debug purposes.
All the same can be done to JArrays.
Printing out values
-------------------
All the classes (JSON, JArray, JString, JNumber, JBoolean and JNull) have ToString()
method overridden to print out information of the object. This meant to be just debug
information about the object. In case of JSON, amount or key/value pairs in object.
In case of JArray, count of objects and their types, or just the value stored in object.
Generally, good for console output since length of the output is always relatively short.
All the classes also have CreateString() method that will print out all the content of
object, in JSON format. (See "Parsing and creating JSON formatted strings" above.)
Serializing and deserializing objects
-------------------------------------
For example, if you have class like
class ExamplePlayer {
public string name;
public bool active;
public List<int> items;
public int? skill;
}
and instance 'examplePlayer' of that class where fields "name", "active" and "items" have
some values set.
You can turn class content to JSON
JSON json = JSON.Serialize(examplePlayer);
And this can be turned to string using CreateString() method like in example above.
Only public fields and fields marked with attribute [UnityEngine.SerializeField] or
[IncludeToJSONSerialize] are serialized. Constant, static and readonly fields are
not serialized. Additionally, you can exclude public fields from serialization by
adding [System.NonSerialized] or [ExcludeFromJSONSerialize] attribute to it.
To other direction, if you have input string like
{"name":"Pingu","active":true,"items":[1,2,4],"skill":null}
Then string values can be copied to class fields by first turning string in to JSON
JSON json = JSON.ParseString(inputString);
and deserialize JSON to class instance
ExamplePlayer examplePlayer = json.Deserialize<ExamplePlayer>();
You now have instance of class ExamplePlayer where field 'name' is "Pingu" etc.
Additional features
===================
Debugging in Unity Editor
-------------------------
For easy debugging, you can follow content of JSON objects in Unity Editor when application
is running.
In your code, you can add any JSON or JArray object to debug by saying
myJsonObject.DebugInEditor("My JSON Object");
where parameter string is name that will appear in debug window.
In Unity Editor, open debug window from menu
Window -> Total JSON -> JSON Runtime Debug
Your objects and their content will appear there.
There is no harm leaving these "DebugInEditor(...)" lines in your code when making build.
They do not have any effect outside Unity Editor.
Debugging in production
-----------------------
Nothing is perfect and it may happen that JSON data you are trying to parse or handle
is invalid. In editor this isn't so much problem but in production builds all you may
get is exception like for example
> JSONKeyNotFoundException: Value for key "id" does not exist in this JSON
Depending on build, it might be that there isn't any stack trace available. If your
project does handle lots of JSON objects, above error message may not tell you at all
where the problem occurred.
This is why TotalJSON allows you to add Debug ID to JSON objects. For example:
JSON playerJSON = getPlayerJSONFromServerData();
playerJSON.SetDebugIDForExceptions("Player data from server");
If now any exceptions happens when handling 'playerJSON', they'll look like this:
> JSONKeyNotFoundException: Value for key "id" does not exist in this JSON - JSON Debug ID: "Player data from server"
So you'll immediately know which JSON caused the exception even if stacktrace is not
available.
This Debug ID string can be added already when parsing JSON:
string playerDataString = <json formatted data here>
JSON playerJSON = JSON.ParseString(playerDataString, "Player data from server");
In this case, Debug ID is added to exceptions already if they happen when parsing
JSON data. If parsing goes fine, that same Debug ID (in this case "Player data from
server") is added to resulting JSON object, so there's no need to use
SetDebugIDForExceptions(string) separately.
JSON validator
--------------
Open JSON validator from Unity Editor menu
Window -> Total JSON -> JSON Validator
To this window you can copy&paste JSON objects or arrays and click Validate button below.
Not only this will check that JSON is in valid format, but it will also make it much more
readable by adding indents and line feeds.
Validator will also make extra effort trying to remove leading or trailing texts that are
not part of JSON object. So you can for example copy text directly from Unity Console with
stack traces. As long as there is some JSON object in the text.
Customized string output
------------------------
When turning JSON object to string using CreateString() method, it is possible to customize
output string using CreateStringSettings.
string customOutput = json.CreateString( new CreateStringSettings() {
HumanReadable = true,
NewLine = CreateStringSettings.NewLineTypes.LF
});
Mostly this is needed when outputting human readable JSON. CreateStringSettings allows for
example changing type and size of indentation, character that is used for line feed etc.
Protecting JSON objects
-----------------------
You can set JSON or JArray objects protected using
json.SetProtected();
This will set this JSON object and all other objects it contains to write protected.
Nothing can be added, moved or changed. This is useful to make sure no accidental changes
are made to objects that should be only for reading.
Once this is set, pretection can't be removed.
Examples
========
TotalJSON package have directory Examples that contains example scene and multiple example
scripts.
Full API docs
=============
All the classes have full inline C# documentation that is also available online in HTML format:
http://www.leguar.com/unity/totaljson/apidoc/1.8/
Feedback
========
If you are happy with this asset, please rate us or leave feedback in Unity Asset Store:
https://assetstore.unity.com/packages/slug/130344
If you have any problems, or maybe suggestions for future versions, feel free to contact:
http://www.leguar.com/contact/?about=totaljson

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 68dcde4a16eb0ea40b1686d871fa55af
timeCreated: 1539193207
licenseType: Store
TextScriptImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 8078f1a0681c06540a7d9d8999226ba7
folderAsset: yes
timeCreated: 1539193094
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 97069a453ee85044eb569c9e2537607f
folderAsset: yes
timeCreated: 1590931574
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,22 @@
// ExcludeFromJSONSerialize
using System;
namespace Leguar.TotalJSON {
/// <summary>
/// Attribute that can be used to exclude single field from JSON serialization. With default serialization settings, this does same as System.NonSerialized attribute.
/// </summary>
[AttributeUsage(AttributeTargets.Field, Inherited = false)]
public sealed class ExcludeFromJSONSerializeAttribute : Attribute {
/// <summary>
/// Constructor for new ExcludeFromJSONSerialize attribute.
/// </summary>
public ExcludeFromJSONSerializeAttribute() {
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 034c500d71cd9534495808dd214850aa
timeCreated: 1590931574
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,22 @@
// IncludeToJSONSerialize
using System;
namespace Leguar.TotalJSON {
/// <summary>
/// Attribute that can be used to include single field to JSON serialization. With default serialization settings, this does same as UnityEngine.SerializeField attribute.
/// </summary>
[AttributeUsage(AttributeTargets.Field, Inherited = false)]
public sealed class IncludeToJSONSerializeAttribute : Attribute {
/// <summary>
/// Constructor for new IncludeToJSONSerialize attribute.
/// </summary>
public IncludeToJSONSerializeAttribute() {
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 8ba9598d27e19bb4390b76212069d33d
timeCreated: 1590931574
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 16c2aac88e0f4124097642e0c257e5d0
folderAsset: yes
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,54 @@
// DeserializeException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if something goes wrong when deserializing JSON to objects.
/// </summary>
public class DeserializeException : ArgumentException {
private DeserializeException(string message) : base(message) {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
internal static DeserializeException forDictionaryKeyTypeNotString(Type type, string toFieldName) {
string fullMessage = "Can not deserialize to dictionary where key type is '"+type.GetType()+"'"+getToFieldNameString(toFieldName)+". Key type need to be string, or allow more loose options using DeserializeSettings";
return (new DeserializeException(fullMessage));
}
internal static DeserializeException forDictionaryKeyTypeNotKnown(Type type, string toFieldName) {
string fullMessage = "Can not deserialize to dictionary where key type is '"+type.GetType()+"'"+getToFieldNameString(toFieldName)+". Key type is none of the supported";
return (new DeserializeException(fullMessage));
}
internal static DeserializeException forNonMatchingType(JValue jValue, Type type, string toFieldName) {
string fullMessage = "Can not deserialize '"+jValue.GetType()+"' to object which type is '"+type+"'"+getToFieldNameString(toFieldName);
return (new DeserializeException(fullMessage));
}
internal static DeserializeException forNoMatchingField(string fieldName, Type type) {
string fullMessage = "Can't find field named '"+fieldName+"' needed for object type '"+type+"'. Values for all fields need to exist, or allow more loose options using DeserializeSettings";
return (new DeserializeException(fullMessage));
}
internal static DeserializeException forNoMatchingValue(Type type) {
string fullMessage = "Not all JSON values were used when populating object type '"+type+"'. Used DeserializeSettings requires that all fields are used";
return (new DeserializeException(fullMessage));
}
private static string getToFieldNameString(string toFieldName) {
return (string.IsNullOrEmpty(toFieldName) ? "" : " (field \""+toFieldName+"\")");
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: d739cecfd5833dc42bd95ea1ee004e93
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
// JArgumentException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if some JSON, JArray or JNumber parameter is invalid.
/// </summary>
public class JArgumentException : ArgumentException {
internal JArgumentException(string message, string paramName)
: base(message,paramName) {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 4da601bc20dfdc642ad5c19464fb980a
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
// JArgumentNullException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if some JSON, JArray or JString parameter is null when it is not allowed to be null.
/// </summary>
public class JArgumentNullException : ArgumentNullException {
internal JArgumentNullException(string paramName, string message)
: base(paramName,message) {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: c292f493140d1f6409bd3f0d25242435
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
// JArrayIndexOutOfRangeException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if some JArray method parameter is out of range.
/// </summary>
public class JArrayIndexOutOfRangeException : ArgumentOutOfRangeException {
internal JArrayIndexOutOfRangeException(string paramName, int actualValue, string message)
: base(paramName,actualValue,message) {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 3c678893eebfa4b4f955712f5da64aa8
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
// JNumberFormatException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if trying to read JNumber value in wrong format, for example float as int.
/// </summary>
public class JNumberFormatException : FormatException {
internal JNumberFormatException(string valueAsString, string wantedType)
: base("JNumber value ("+valueAsString+") is floating point number and can't be returned as "+wantedType) {
}
internal JNumberFormatException(string valueAsString)
: base("JNumber value ("+valueAsString+") is not valid decimal number") { // (contains E/e notation, consider reading this value as double or float)
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 969a97261570e1e4697cb1fa851fe6ec
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
// JNumberOverflowException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if trying to read JNumber value in format where it doesn't fit. For example trying to read number 2147483648 as int.
/// </summary>
public class JNumberOverflowException : OverflowException {
internal JNumberOverflowException(string valueAsString, string wantedType, string minValue, string maxValue)
: base("JNumber value ("+valueAsString+") is outside "+wantedType+" range ["+minValue+".."+maxValue+"]") {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: f205c82ee9338384c8f040c98dabc3de
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
// JSONKeyAlreadyExistsException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if JSON already contains certain key and trying to add it again.
/// </summary>
public class JSONKeyAlreadyExistsException : ArgumentException {
internal JSONKeyAlreadyExistsException(string message)
: base(message,"key") {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 77652c275db7f6047830bf596953706c
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
// JSONKeyNotFoundException
using System.Collections.Generic;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if given parameter key doesn't exist in JSON.
/// </summary>
public class JSONKeyNotFoundException : KeyNotFoundException {
internal JSONKeyNotFoundException(string message)
: base(message) {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: e47b0f3992e0232419eac53940948159
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,30 @@
// JValueNullException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception thrown if trying to read value which is null while that is not allowed.
/// </summary>
public class JValueNullException : JValueTypeException {
internal JValueNullException(string key, string triedType, string exceptionMessageTail)
: base("Can not read value mapped to key \""+key+"\" as "+triedType+", value is null"+exceptionMessageTail) {
}
internal JValueNullException(int index, string triedType)
: base("Can not read value at index "+index+" as "+triedType+", value is null") {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 43ec8a0036358ec41b40c1a534330183
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
// JValueTypeException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception thrown if trying to read value which is different type than requested. For example trying to read bool (JBoolean) as string (JString).
/// </summary>
public class JValueTypeException : InvalidCastException {
internal JValueTypeException(string key, JValue realValue, string triedType, string exceptionMessageTail)
: base("Can not cast value mapped to key \""+key+"\" to "+triedType+", value type is "+realValue.GetType()+exceptionMessageTail) {
}
internal JValueTypeException(int arrayIndex, JValue realValue, string triedType)
: base("Can not cast array element at index "+arrayIndex+" to "+triedType+", element type is "+realValue.GetType()) {
}
protected JValueTypeException(string message)
: base(message) {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: dd4e8553edfa51747a9f603037136b60
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,72 @@
// ParseException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception thrown if parsing string to JSON or JArray fails.
/// </summary>
public class ParseException : ArgumentException {
private ParseException(string message) : base(message) {
}
internal static ParseException forEmpty(String message, ParseStringSettings parseStrignSettings) {
string fullMessage=message+getExceptionMessageTail(parseStrignSettings);
return (new ParseException(fullMessage));
}
internal static ParseException forInvalidStart(String message, ParseStringRunner parseStrignRunner) {
StringPointer sp=parseStrignRunner.getStringPointer();
string fullMessage=message+" - "+sp.getLineAndColumnForException()+getExceptionMessageTail(parseStrignRunner);
return (new ParseException(fullMessage));
}
internal static ParseException forInvalidCharacter(String message, ParseStringRunner parseStrignRunner) {
StringPointer sp=parseStrignRunner.getStringPointer();
string fullMessage=message+" - "+sp.getLineAndColumnForException()+", near: "+sp.getSubStringForException(32)+getExceptionMessageTail(parseStrignRunner);
return (new ParseException(fullMessage));
}
internal static ParseException forInvalidEnd(ParseStringRunner parseStrignRunner) {
StringPointer sp=parseStrignRunner.getStringPointer();
string fullMessage="Unexpected end of input - "+sp.getLineAndColumnForException()+", near: "+sp.getSubStringForException(16)+getExceptionMessageTail(parseStrignRunner);
return (new ParseException(fullMessage));
}
internal static ParseException forCharactersAfterEnd(ParseStringRunner parseStrignRunner) {
StringPointer sp=parseStrignRunner.getStringPointer();
string fullMessage="Unexpected non-white character after end of object - "+sp.getLineAndColumnForException()+", near: "+sp.getSubStringForException(32)+getExceptionMessageTail(parseStrignRunner);
return (new ParseException(fullMessage));
}
private static string getExceptionMessageTail(ParseStringRunner parseStringRunner) {
if (parseStringRunner!=null) {
return getExceptionMessageTailForID(parseStringRunner.getParseDebugIDForExceptions());
}
return getExceptionMessageTailForID(null);
}
internal static string getExceptionMessageTail(ParseStringSettings parseStringSettings) {
if (parseStringSettings!=null) {
return getExceptionMessageTailForID(parseStringSettings.DebugIDForExceptions);
}
return getExceptionMessageTailForID(null);
}
internal static string getExceptionMessageTailForID(string debugIDForExceptions) {
return InternalTools.getExceptionMessageTailForID(debugIDForExceptions,"Parse");
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 9e4ae93c61b48af488cbf680e3f56180
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
// ProtectedException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception thrown if trying to change anything in protected JSON or JArray objects.
/// </summary>
public class ProtectedException : Exception {
internal ProtectedException(string message) : base(message) {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 336cc7907a0696743b7748f5af9b05bc
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
// SerializeException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if something goes wrong when serializing system objects to JSON.
/// </summary>
public class SerializeException : ArgumentException {
internal SerializeException(string message)
: base(message) {
}
internal SerializeException(string message, object problemObject)
: base(message+", object type = "+problemObject.GetType()) {
}
internal SerializeException(string message, object problemObject, string paramName)
: base(message+", object type = "+problemObject.GetType(),paramName) {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: d56315144217402429d47a7e5eeceb95
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,26 @@
// JArgumentNullException
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Exception that is thrown if object added to JSON or JArray is type that can't be converted to any JValue.
/// </summary>
public class UnknownObjectTypeException : JArgumentException {
internal UnknownObjectTypeException(object unknownValue, string paramName)
: base("Parameter object is unknown type '"+unknownValue.GetType().ToString()+"'",paramName) {
}
public override string StackTrace {
get {
return InternalTools.getCleanedStackTrace(base.StackTrace);
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 951941f4547f23840810348b4969ba00
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: aeff757c46539624ea433dfad5d5d062
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,115 @@
// JValue - JBoolean
using System;
using System.Text;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Class to store boolean value in JSON format. Once JBoolean instance is created, its value can't be changed.
/// </summary>
public class JBoolean : JValue {
private const string TRUE="true";
private const string FALSE="false";
private bool boolValue;
/// <summary>
/// Creates new instance of JBoolean class.
/// </summary>
/// <param name="value">
/// Boolean value stored to this object.
/// </param>
public JBoolean(bool boolValue) : base() {
this.boolValue = boolValue;
}
public override string ToString() {
return ("[JBoolean: "+(boolValue?TRUE:FALSE)+"]");
}
/// <summary>
/// Test if another object equals to this object. Always returns false if parameter object is null or it is not instance of JBoolean.
/// Two JBoolean objects are equal if both contains same boolean value.
/// </summary>
/// <param name="anotherObject">
/// Another object that is compared to this one.
/// </param>
/// <returns>
/// True if objects are equal, false otherwise.
/// </returns>
public override bool Equals(object anotherObject) {
if (anotherObject==null) {
return false;
}
if (!(anotherObject is JBoolean)) {
return false;
}
JBoolean anotherJBoolean=(JBoolean)(anotherObject);
return (boolValue==anotherJBoolean.AsBool());
}
public override int GetHashCode() {
return (boolValue?1:0);
}
/// <summary>
/// Get value of this JSON boolean as c# system bool.
/// </summary>
/// <returns>
/// System bool value.
/// </returns>
public bool AsBool() {
return boolValue;
}
internal override void zCreate(CreateStringRunner createStringRunner) {
createStringRunner.append(boolValue?TRUE:FALSE);
}
internal static JBoolean zParse(ParseStringRunner parseStringRunner, bool expectingTrue) {
StringPointer sp = parseStringRunner.getStringPointer();
if (expectingTrue) {
if (sp.isNextChars(TRUE.Substring(1))) {
return (new JBoolean(true));
} else {
throw ParseException.forInvalidCharacter("Invalid string when expecting '"+TRUE+"'",parseStringRunner);
}
} else {
if (sp.isNextChars(FALSE.Substring(1))) {
return (new JBoolean(false));
} else {
throw ParseException.forInvalidCharacter("Invalid string when expecting '"+FALSE+"'",parseStringRunner);
}
}
}
internal override object zDeserialize(Type type, string toFieldName, DeserializeSettings deserializeSettings) {
// In case type is nullable type "bool?"
Type nullableType = Nullable.GetUnderlyingType(type);
if (nullableType != null) {
return this.zDeserialize(nullableType, toFieldName, deserializeSettings);
}
if (type==typeof(bool)) {
return this.AsBool();
}
if (type==typeof(object) && deserializeSettings.AllowFieldsToBeObjects) {
return this.AsBool();
}
throw (DeserializeException.forNonMatchingType(this,type,toFieldName));
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 1e8c311d10eb1fd469a766c3c9debde0
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,84 @@
// JValue - JNull
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Class to store null value in JSON format.
/// </summary>
public class JNull : JValue {
private const string NULL="null";
/// <summary>
/// Creates new JNull object.
/// </summary>
public JNull() : base() {
}
public override string ToString() {
return ("[JNull]");
}
/// <summary>
/// Test if another object equals to this object. This method always returns true if parameter object is instance of JNull, but false if parameter is system null.
/// </summary>
/// <param name="anotherObject">
/// Another object that is compared to this one.
/// </param>
/// <returns>
/// True if objects are equal, false otherwise.
/// </returns>
public override bool Equals(object anotherObject) {
if (anotherObject==null) {
return false;
}
if (!(anotherObject is JNull)) {
return false;
}
return true;
}
public override int GetHashCode() {
return 101;
}
internal override void zCreate(CreateStringRunner createStringRunner) {
createStringRunner.append(NULL);
}
internal static JNull zParse(ParseStringRunner parseStringRunner) {
StringPointer sp = parseStringRunner.getStringPointer();
if (sp.isNextChars(NULL.Substring(1))) {
return (new JNull());
} else {
throw ParseException.forInvalidCharacter("Invalid string when expecting '"+NULL+"'",parseStringRunner);
}
}
internal override object zDeserialize(Type type, string toFieldName, DeserializeSettings deserializeSettings) {
// Do at least some basic checking that not trying to add null to number or boolean field, as trying to set null to these objects using FieldInfo doesn't cause exception.
// If field type is nullable like "bool?" or "int?", type is also System.Nullable so this check doesn't prevent adding null value to those fields.
if (type==typeof(float) || type==typeof(double) || type==typeof(decimal)
|| type==typeof(int) || type==typeof(long) || type==typeof(short) || type==typeof(byte)
|| type==typeof(uint) || type==typeof(ulong) || type==typeof(ushort) || type==typeof(sbyte)
|| type==typeof(bool)) {
throw (DeserializeException.forNonMatchingType(this,type,toFieldName));
}
// bool canBeNull = !type.IsValueType || (Nullable.GetUnderlyingType(type) != null);
return null;
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: a6590f14a3524344684bb0378328c57a
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,751 @@
// JValue - JNumber
using System;
using System.Text;
using System.Globalization;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Class to store number value in JSON format. Once JNumber instance is created, its value can't be changed.
///
/// There is no limit how long or big numbers can be, but trying to read too big number for example as long will cause exception.
/// Oversized numbers can be still read out and handled as strings.
/// </summary>
public class JNumber : JValue {
private readonly string valueAsString;
/// <summary>
/// Creates new JSON number value from string. There is no limits in number size as long as it follows json number format.
/// </summary>
/// <param name="numberAsString">
/// Value for this JNumber object in string format.
/// </param>
/// <exception cref="JArgumentException">
/// If parameter string is not valid number.
/// </exception>
public JNumber(string numberAsString) : base() {
string errorMessage=numberFormatCheck(numberAsString);
if (errorMessage!=null) {
throw (new JArgumentException("Parameter \""+numberAsString+"\" is not valid JSON format number: "+errorMessage,"numberAsString"));
}
valueAsString = numberAsString;
}
/// <summary>
/// Creates new JSON number value from c# int value.
/// </summary>
/// <param name="numberAsInt">
/// Value for this JNumber object.
/// </param>
public JNumber(int numberAsInt) : base() {
valueAsString=safeLongAsString(numberAsInt);
}
/// <summary>
/// Creates new JSON number value from c# long value.
/// </summary>
/// <param name="numberAsLong">
/// Value for this JNumber object.
/// </param>
public JNumber(long numberAsLong) : base() {
valueAsString=safeLongAsString(numberAsLong);
}
/// <summary>
/// Creates new JSON number value from c# float value.
/// </summary>
/// <param name="numberAsFloat">
/// Value for this JNumber object.
/// </param>
/// <exception cref="JArgumentException">
/// If parameter is NaN or Infinity.
/// </exception>
public JNumber(float numberAsFloat) : base() {
if (float.IsNaN(numberAsFloat)) {
throw (new JArgumentException("Can not create new JNumber from float that is NaN","numberAsFloat"));
}
if (float.IsPositiveInfinity(numberAsFloat)) {
throw (new JArgumentException("Can not create new JNumber from float that is infinity","numberAsFloat"));
}
if (float.IsNegativeInfinity(numberAsFloat)) {
throw (new JArgumentException("Can not create new JNumber from float that is negative infinity","numberAsFloat"));
}
valueAsString=safeFloatAsString(numberAsFloat);
}
/// <summary>
/// Creates new JSON number value from c# double value.
/// </summary>
/// <param name="numberAsDouble">
/// Value for this JNumber object.
/// </param>
/// <exception cref="JArgumentException">
/// If parameter is NaN or Infinity.
/// </exception>
public JNumber(double numberAsDouble) : base() {
if (double.IsNaN(numberAsDouble)) {
throw (new JArgumentException("Can not create new JNumber from double that is NaN","numberAsDouble"));
}
if (double.IsPositiveInfinity(numberAsDouble)) {
throw (new JArgumentException("Can not create new JNumber from double that is infinity","numberAsDouble"));
}
if (double.IsNegativeInfinity(numberAsDouble)) {
throw (new JArgumentException("Can not create new JNumber from double that is negative infinity","numberAsDouble"));
}
valueAsString=safeDoubleAsString(numberAsDouble);
}
/// <summary>
/// Creates new JSON number value from c# decimal value.
/// </summary>
/// <param name="numberAsDecimal">
/// Value for this JNumber object.
/// </param>
public JNumber(decimal numberAsDecimal) : base() {
valueAsString=addDecimalPoint(numberAsDecimal.ToString(CultureInfo.InvariantCulture));
}
private JNumber(string safeValueAsString, ParseStringRunner parseStringRunner) : base() {
valueAsString=parseStringRunner.getPossiblyFixedNumber(safeValueAsString);
}
public override string ToString() {
return ("[JNumber: "+valueAsString+"]");
}
/// <summary>
/// Test if another object equals to this object. Always returns false if parameter object is null or it is not instance of JNumber.
/// Two JNumber objects are equal if both contains value which string representation is exactly equal.
/// For example JNumber that contains "1" is not equal to JNumber that contains "1.0"
/// </summary>
/// <param name="anotherObject">
/// Another object that is compared to this one.
/// </param>
/// <returns>
/// True if objects are equal, false otherwise.
/// </returns>
public override bool Equals(object anotherObject) {
if (anotherObject==null) {
return false;
}
if (!(anotherObject is JNumber)) {
return false;
}
JNumber anotherJNumber=(JNumber)(anotherObject);
return (valueAsString.Equals(anotherJNumber.AsString()));
}
public override int GetHashCode() {
return valueAsString.GetHashCode();
}
/// <summary>
/// Gets value of this number object as long. This will throw exception if number is floating point number or outside long range.
/// </summary>
/// <returns>
/// Value as long.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in long.
/// </exception>
/// <exception cref="JNumberFormatException">
/// If number stored to this JNumber is floating point number.
/// </exception>
public long AsLong() {
try {
return long.Parse(valueAsString,CultureInfo.InvariantCulture);
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"long",""+long.MinValue,""+long.MaxValue));
}
catch (FormatException) {
throw (new JNumberFormatException(valueAsString,"long"));
}
}
/// <summary>
/// Gets value of this number object as unsigned long. This will throw exception if number is floating point number or outside ulong range.
/// </summary>
/// <returns>
/// Value as ulong.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in ulong.
/// </exception>
/// <exception cref="JNumberFormatException">
/// If number stored to this JNumber is floating point number.
/// </exception>
public ulong AsULong() {
try {
return ulong.Parse(valueAsString,CultureInfo.InvariantCulture);
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"ulong",""+ulong.MinValue,""+ulong.MaxValue));
}
catch (FormatException) {
throw (new JNumberFormatException(valueAsString,"ulong"));
}
}
/// <summary>
/// Gets value of this number object as int. This will throw exception if number is floating point number or outside int range.
/// </summary>
/// <returns>
/// Value as int.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in int.
/// </exception>
/// <exception cref="JNumberFormatException">
/// If number stored to this JNumber is floating point number.
/// </exception>
public int AsInt() {
try {
return int.Parse(valueAsString,CultureInfo.InvariantCulture);
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"int",""+int.MinValue,""+int.MaxValue));
}
catch (FormatException) {
throw (new JNumberFormatException(valueAsString,"int"));
}
}
/// <summary>
/// Gets value of this number object as unsigned int. This will throw exception if number is floating point number or outside uint range.
/// </summary>
/// <returns>
/// Value as uint.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in uint.
/// </exception>
/// <exception cref="JNumberFormatException">
/// If number stored to this JNumber is floating point number.
/// </exception>
public uint AsUInt() {
try {
return uint.Parse(valueAsString,CultureInfo.InvariantCulture);
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"uint",""+uint.MinValue,""+uint.MaxValue));
}
catch (FormatException) {
throw (new JNumberFormatException(valueAsString,"uint"));
}
}
/// <summary>
/// Gets value of this number object as short. This will throw exception if number is floating point number or outside short range.
/// </summary>
/// <returns>
/// Value as short.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in short.
/// </exception>
/// <exception cref="JNumberFormatException">
/// If number stored to this JNumber is floating point number.
/// </exception>
public short AsShort() {
try {
return short.Parse(valueAsString,CultureInfo.InvariantCulture);
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"short",""+short.MinValue,""+short.MaxValue));
}
catch (FormatException) {
throw (new JNumberFormatException(valueAsString,"short"));
}
}
/// <summary>
/// Gets value of this number object as unsigned short. This will throw exception if number is floating point number or outside ushort range.
/// </summary>
/// <returns>
/// Value as ushort.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in ushort.
/// </exception>
/// <exception cref="JNumberFormatException">
/// If number stored to this JNumber is floating point number.
/// </exception>
public ushort AsUShort() {
try {
return ushort.Parse(valueAsString,CultureInfo.InvariantCulture);
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"ushort",""+ushort.MinValue,""+ushort.MaxValue));
}
catch (FormatException) {
throw (new JNumberFormatException(valueAsString,"ushort"));
}
}
/// <summary>
/// Gets value of this number object as byte. This will throw exception if number is floating point number or outside byte range.
/// </summary>
/// <returns>
/// Value as byte.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in byte.
/// </exception>
/// <exception cref="JNumberFormatException">
/// If number stored to this JNumber is floating point number.
/// </exception>
public byte AsByte() {
try {
return byte.Parse(valueAsString,CultureInfo.InvariantCulture);
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"byte",""+byte.MinValue,""+byte.MaxValue));
}
catch (FormatException) {
throw (new JNumberFormatException(valueAsString,"byte"));
}
}
/// <summary>
/// Gets value of this number object as signed byte. This will throw exception if number is floating point number or outside sbyte range.
/// </summary>
/// <returns>
/// Value as sbyte.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in sbyte.
/// </exception>
/// <exception cref="JNumberFormatException">
/// If number stored to this JNumber is floating point number.
/// </exception>
public sbyte AsSByte() {
try {
return sbyte.Parse(valueAsString,CultureInfo.InvariantCulture);
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"sbyte",""+sbyte.MinValue,""+sbyte.MaxValue));
}
catch (FormatException) {
throw (new JNumberFormatException(valueAsString,"sbyte"));
}
}
/// <summary>
/// Gets value of this number object as double. This will throw exception if number is outside double range.
/// </summary>
/// <returns>
/// Value as double.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in double.
/// </exception>
public double AsDouble() {
try {
double value=double.Parse(valueAsString,CultureInfo.InvariantCulture);
if (double.IsInfinity(value)) {
throw (new OverflowException());
}
return value;
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"double",""+double.MinValue,""+double.MaxValue));
}
}
/// <summary>
/// Gets value of this number object as float. This will throw exception if number is outside float range.
/// </summary>
/// <returns>
/// Value as float.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in float.
/// </exception>
public float AsFloat() {
try {
float value=float.Parse(valueAsString,CultureInfo.InvariantCulture);
if (float.IsInfinity(value)) {
throw (new OverflowException());
}
return value;
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"float",""+float.MinValue,""+float.MaxValue));
}
}
/// <summary>
/// Gets value of this number object as decimal. This will throw exception if number is outside decimal range or number contains E/e notation.
/// </summary>
/// <returns>
/// Value as decimal.
/// </returns>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in decimal.
/// </exception>
/// <exception cref="JNumberFormatException">
/// If number stored to this JNumber uses E/e notation (like 1.234567e89)
/// </exception>
public decimal AsDecimal() {
try {
return decimal.Parse(valueAsString,CultureInfo.InvariantCulture);
}
catch (OverflowException) {
throw (new JNumberOverflowException(valueAsString,"decimal",""+decimal.MinValue,""+decimal.MaxValue));
}
catch (FormatException) {
throw (new JNumberFormatException(valueAsString));
}
}
/// <summary>
/// Gets value of this number as string.
/// </summary>
/// <returns>
/// Value as string.
/// </returns>
public string AsString() {
return valueAsString;
}
/// <summary>
/// Gets value of this number as object. First fitting value of these are returned: int, long, float, double
/// </summary>
/// <exception cref="JNumberOverflowException">
/// If number stored to this JNumber doesn't fit in double.
/// </exception>
/// <returns>
/// Value as object, that may be one of the 4 basic number objects.
/// </returns>
public object AsObject() {
int iValue;
if (int.TryParse(valueAsString, NumberStyles.Integer, CultureInfo.InvariantCulture, out iValue)) {
return iValue;
}
long lValue;
if (long.TryParse(valueAsString, NumberStyles.Integer, CultureInfo.InvariantCulture, out lValue)) {
return lValue;
}
float fValue;
if (float.TryParse(valueAsString, NumberStyles.Float, CultureInfo.InvariantCulture, out fValue)) {
if (!float.IsInfinity(fValue)) {
return fValue;
}
}
// This could fail too in extreme cases, but custom exception is thrown
return this.AsDouble();
}
internal override void zCreate(CreateStringRunner createStringRunner) {
createStringRunner.append(this.AsString());
}
internal static JNumber zParse(ParseStringRunner parseStringRunner, char firstChr) {
StringPointer sp = parseStringRunner.getStringPointer();
int start=sp.getCurrentIndex()-1; // -1 since first character is already read
bool valid=parseCheck(sp,firstChr);
if (!valid) {
throw ParseException.forInvalidCharacter("Invalid number value \""+sp.getSubStringStartingFrom(start)+"\"",parseStringRunner);
} else {
sp.stepBack();
string validNumber=sp.getSubStringStartingFrom(start);
return (new JNumber(validNumber,parseStringRunner));
}
}
private static bool parseCheck(StringPointer sp, char chr) {
int state;
if (chr=='-') {
chr=sp.getNextChar();
}
if (chr=='0') {
chr=sp.getNextChar();
if (chr=='.') {
state=5;
} else if (chr=='e' || chr=='E') {
state=7;
} else {
return true; // (-)0
}
} else if (chr>='1' && chr<='9') {
state=4;
} else {
return false;
}
do {
chr=sp.getNextChar();
if (state==4) {
if (chr>='0' && chr<='9') {
state=4;
} else if (chr=='.') {
state=5;
} else if (chr=='e' || chr=='E') {
state=7;
} else {
return true; // (-)##
}
} else if (state==5) {
if (chr>='0' && chr<='9') {
state=6;
} else {
return false;
}
} else if (state==6) {
if (chr>='0' && chr<='9') {
state=6;
} else if (chr=='e' || chr=='E') {
state=7;
} else {
return true; // (-)(##).##
}
} else if (state==7) {
if (chr=='+' || chr=='-') {
chr=sp.getNextChar();
if (chr>='0' && chr<='9') {
state=9;
} else {
return false;
}
} else if (chr>='0' && chr<='9') {
state=9;
} else {
return false;
}
} else if (state==9) {
if (chr>='0' && chr<='9') {
state=9;
} else {
return true; // (-)(##).##[e/E](+/-)##
}
}
} while (true);
}
private static string numberFormatCheck(string str) {
int count=str.Length,
state=1;
for (int index=0; index<count; index++) {
char chr=str[index];
if (state==1) { // Minus or first digit
if (chr=='-') {
state=2;
} else if (chr=='0') {
state=3;
} else if (chr>='1' && chr<='9') {
state=4;
} else {
return ("Invalid first character '"+chr+"', should be digit or minus sign");
}
} else if (state==2) { // First digit after minus
if (chr=='0') {
state=3;
} else if (chr>='1' && chr<='9') {
state=4;
} else {
return ("Expecting at least one digit after minus sign, got '"+chr+"' instead");
}
} else if (state==3) { // Number started with (minus) zero, only decimal point or E can follow
if (chr=='.') {
state=5;
} else if (chr=='e' || chr=='E') {
state=7;
} else {
return ("Only decimal point or E/e can follow number starting with 0 or -0, got '"+chr+"' instead");
}
} else if (state==4) { // Digits before decimal point or E
if (chr=='.') {
state=5;
} else if (chr=='e' || chr=='E') {
state=7;
} else if (chr<'0' || chr>'9') {
return ("Invalid character '"+chr+"' (before possible decimal point or E/e)");
}
} else if (state==5) { // Need at least one digit after decimal point
if (chr>='0' && chr<='9') {
state=6;
} else {
return ("Need at least one digit after decimal point, got '"+chr+"' instead");
}
} else if (state==6) { // Following digits after decimal point
if (chr=='e' || chr=='E') {
state=7;
} else if (chr<'0' || chr>'9') {
return ("Invalid character '"+chr+"' after decimal point");
}
} else if (state==7) { // Plus, minus or digit after E
if (chr=='+' || chr=='-') {
state=8;
} else if (chr>='0' && chr<='9') {
state=9;
} else {
return ("Expecting digit or plus/minus sign after E/e, got '"+chr+"' instead");
}
} else if (state==8) { // Need at least one digit after E plus/minus,
if (chr>='0' && chr<='9') {
state=9;
} else {
return ("Expecting digit after plus/minus sign after E/e, got '"+chr+"' instead");
}
} else if (state==9) { // Following digits after E
if (chr<'0' || chr>'9') {
return ("Invalid character '"+chr+"' in digits after E/e");
}
}
}
if (state==1) {
return "String is empty";
}
if (state==2) {
return "String contains only minus sign";
}
if (state==5) {
return "No digits after decimal point";
}
if (state==7) {
return "Need at least one digit after E/e";
}
if (state==8) {
return "Need at least one digit after plus/minus sign after E/e";
}
return null;
}
private string safeFloatAsString(float value) {
// Basic change that doesn't add too many decimals
string basicStr=value.ToString(CultureInfo.InvariantCulture);
basicStr=addDecimalPoint(basicStr);
try {
float reverse=float.Parse(basicStr,CultureInfo.InvariantCulture);
if (reverse.Equals(value)) { // May not be true because rounding
return basicStr;
}
}
catch (OverflowException) {
// This happens because rounding if value is close min/max
}
// Try out with more decimals
string rStr=value.ToString("R",CultureInfo.InvariantCulture);
rStr=addDecimalPoint(rStr);
try {
float reverse=float.Parse(rStr,CultureInfo.InvariantCulture);
if (reverse.Equals(value)) {
return rStr;
}
}
catch (Exception) {
}
// If neither works, fall back to simplest
return basicStr;
}
private string safeDoubleAsString(double value) {
// Basic change that doesn't add too many decimals
string basicStr=value.ToString(CultureInfo.InvariantCulture);
basicStr=addDecimalPoint(basicStr);
try {
double reverse=double.Parse(basicStr,CultureInfo.InvariantCulture);
if (reverse.Equals(value)) {
return basicStr;
}
}
catch (OverflowException) {
// This happens because rounding if value is close min/max
}
// Try out with more decimals
string rStr=value.ToString("R",CultureInfo.InvariantCulture);
rStr=addDecimalPoint(rStr);
try {
double reverse=double.Parse(rStr,CultureInfo.InvariantCulture);
if (reverse.Equals(value)) {
return rStr;
}
}
catch (Exception) {
}
// If neither works, fall back to simplest
return basicStr;
}
private static string addDecimalPoint(string str) {
if (str.IndexOf('E')==-1 && str.IndexOf('e')==-1 && str.IndexOf('.')==-1) {
str+=".0";
}
return str;
}
private static string safeLongAsString(long value) {
return value.ToString(CultureInfo.InvariantCulture);
}
private static string safeULongAsString(ulong value) {
return value.ToString(CultureInfo.InvariantCulture);
}
internal override object zDeserialize(Type type, string toFieldName, DeserializeSettings deserializeSettings) {
// In case type is nullable type, for example "int?"
Type nullableType = Nullable.GetUnderlyingType(type);
if (nullableType != null) {
return this.zDeserialize(nullableType, toFieldName, deserializeSettings);
}
if (type==typeof(float)) {
return this.AsFloat();
}
if (type==typeof(double)) {
return this.AsDouble();
}
if (type==typeof(decimal)) {
return this.AsDecimal();
}
if (type==typeof(int)) {
return this.AsInt();
}
if (type==typeof(long)) {
return this.AsLong();
}
if (type==typeof(short)) {
return this.AsShort();
}
if (type==typeof(byte)) {
return this.AsByte();
}
if (type==typeof(uint)) {
return this.AsUInt();
}
if (type==typeof(ulong)) {
return this.AsULong();
}
if (type==typeof(ushort)) {
return this.AsUShort();
}
if (type==typeof(sbyte)) {
return this.AsSByte();
}
if (type==typeof(object) && deserializeSettings.AllowFieldsToBeObjects) {
return this.AsObject();
}
throw (DeserializeException.forNonMatchingType(this,type,toFieldName));
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 23275ca83e39b864188eecf9c5fa19ee
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 2ac3101645eb62d46b49e8887468095c
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,211 @@
// JValue - JString
using System;
using System.Text;
using System.Collections.Generic;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Class to store string value in JSON format. Once JString instance is created, its value can't be changed.
/// </summary>
public class JString : JValue { // , IEquatable<JString> {
private const string HEX="0123456789ABCDEF";
private string stringValue;
/// <summary>
/// Creates new instance of JString object.
///
/// Parameter can't be null. If you wish to add null to JSON or JArray object, create <code>new JNull()</code> and add that one.
/// </summary>
/// <param name="stringValue">
/// C# string value to be stored in this object.
/// </param>
/// <exception cref="JArgumentNullException">
/// If parameter is null.
/// </exception>
public JString(string stringValue) : base() {
if (stringValue==null) {
throw (new JArgumentNullException("stringValue","Parameter can not be null in constructor JString.<init>(string)"));
}
this.stringValue=stringValue;
}
public override string ToString() {
int length = stringValue.Length;
if (length==0) {
return ("[JString: Empty string]");
} else {
return ("[JString: \""+stringValue+"\" ("+length+" character"+(length>1?"s":"")+")]");
}
}
/// <summary>
/// Test if another object equals to this object. Always returns false if parameter object is null or it is not instance of JString.
/// Two JString objects are equal if both contains exactly same string.
/// </summary>
/// <param name="anotherObject">
/// Another object that is compared to this one.
/// </param>
/// <returns>
/// True if objects are equal, false otherwise.
/// </returns>
public override bool Equals(object anotherObject) {
if (anotherObject==null) {
return false;
}
if (!(anotherObject is JString)) {
return false;
}
JString anotherJString=(JString)(anotherObject);
return (stringValue.Equals(anotherJString.AsString()));
}
public override int GetHashCode() {
return stringValue.GetHashCode();
}
/// <summary>
/// Get value of this JSON string as c# system string.
/// </summary>
/// <returns>
/// c# string value, can not be null.
/// </returns>
public string AsString() {
return stringValue;
}
internal override void zCreate(CreateStringRunner createStringRunner) {
encode(createStringRunner,stringValue);
}
internal static void encode(CreateStringRunner createStringRunner, string str) {
createStringRunner.append('"');
foreach (char chr in str) {
if (chr=='"') {
createStringRunner.append("\\\"");
} else if (chr=='\\') {
createStringRunner.append("\\\\");
} else if (chr=='/' && createStringRunner.isEscapeForwardSlashes()) {
createStringRunner.append("\\/");
} else if (chr=='\b') {
createStringRunner.append("\\b");
} else if (chr=='\f') {
createStringRunner.append("\\f");
} else if (chr=='\n') {
createStringRunner.append("\\n");
} else if (chr=='\r') {
createStringRunner.append("\\r");
} else if (chr=='\t') {
createStringRunner.append("\\t");
} else if (chr<32 || chr>126) { // } else if (chr<32 || (chr>126 && createStringRunner.isEncodeNon7bitCharacters())) {
if (chr<16) {
createStringRunner.append("\\u000");
createStringRunner.append(HEX[chr]);
} else if (chr<256) {
createStringRunner.append("\\u00");
createStringRunner.append(HEX[chr/16]);
createStringRunner.append(HEX[chr%16]);
} else if (chr<4096) {
createStringRunner.append("\\u0");
createStringRunner.append(HEX[chr/256]);
createStringRunner.append(HEX[(chr%256)/16]);
createStringRunner.append(HEX[chr%16]);
} else {
createStringRunner.append("\\u");
createStringRunner.append(HEX[chr/4096]);
createStringRunner.append(HEX[(chr%4096)/256]);
createStringRunner.append(HEX[(chr%256)/16]);
createStringRunner.append(HEX[chr%16]);
}
} else {
createStringRunner.append(chr);
}
}
createStringRunner.append('"');
}
internal static JString zParse(ParseStringRunner parseStringRunner, bool expectStartOfString) {
StringPointer sp = parseStringRunner.getStringPointer();
if (expectStartOfString) {
char chr;
if (!sp.tryGetNextNonWhiteChar(out chr)) {
throw ParseException.forInvalidStart("Parameter string didn't contain any non-white characters",parseStringRunner);
}
if (chr!='"') {
throw ParseException.forInvalidStart("Invalid character '"+chr+"' when expecting start of string '\"'",parseStringRunner);
}
}
return (new JString(decode(parseStringRunner)));
}
internal static string decode(ParseStringRunner parseStringRunner) {
// At this point, StringPointer has passed starting "
StringPointer sp = parseStringRunner.getStringPointer();
StringBuilder sb=new StringBuilder();
do {
char chr=sp.getNextChar();
if (chr=='"') {
return sb.ToString();
}
if (chr=='\\') {
chr=sp.getNextChar();
if (chr=='"' || chr=='\\' || chr=='/') {
// 'chr' works as is
} else if (chr=='b') {
chr='\b';
} else if (chr=='f') {
chr='\f';
} else if (chr=='n') {
chr='\n';
} else if (chr=='r') {
chr='\r';
} else if (chr=='t') {
chr='\t';
} else if (chr=='u') {
int ucode=0;
for (int n=0; n<4; n++) {
chr=sp.getNextChar();
int uvalue=HEX.IndexOf(char.ToUpperInvariant(chr));
if (uvalue<0) {
throw ParseException.forInvalidCharacter("Invalid hexadecimal character '"+chr+"' after '\\u' in string value",parseStringRunner);
}
ucode=ucode*16+uvalue;
}
chr=(char)(ucode);
} else {
throw ParseException.forInvalidCharacter("Invalid character '"+chr+"' after '\\' in string value",parseStringRunner);
}
}
sb.Append(chr);
} while (true);
}
internal override object zDeserialize(Type type, string toFieldName, DeserializeSettings deserializeSettings) {
if (type==typeof(string)) {
return this.AsString();
}
if (type==typeof(object) && deserializeSettings.AllowFieldsToBeObjects) {
return this.AsString();
}
throw (DeserializeException.forNonMatchingType(this,type,toFieldName));
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 0ac0f6ca9838f034faae8634da415da2
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,45 @@
// JValue
using System;
using Leguar.TotalJSON.Internal;
namespace Leguar.TotalJSON {
/// <summary>
/// Abstract base class for all JSON objects: JSON, JArray, JNumber, JBoolean, JString and JNull.
/// </summary>
public abstract class JValue {
protected JValue() {
}
/// <summary>
/// Turns this object to JSON formatted string.
/// </summary>
/// <returns>
/// This object as JSON formatted string, containing only basic ascii characters between [32..126] without line feeds.
/// </returns>
public virtual string CreateString() {
return CreateString(new CreateStringSettings());
}
/// <summary>
/// Turns this object to JSON formatted string using specified settings.
/// </summary>
/// <returns>
/// This object as JSON formatted string.
/// </returns>
public virtual string CreateString(CreateStringSettings settings) {
CreateStringRunner createStringRunner = new CreateStringRunner(settings);
zCreate(createStringRunner);
return createStringRunner.getFinalString();
}
internal abstract void zCreate(CreateStringRunner createStringRunner);
internal abstract object zDeserialize(Type type, string toFieldName, DeserializeSettings deserializeSettings);
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: bee442bd1b37b0443b732f66c02dbdd1
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
fileFormatVersion: 2
guid: 127024a622546da49addc03939a56ba7
folderAsset: yes
timeCreated: 1539193114
licenseType: Store
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,129 @@
// CreateStringSettings
using System;
using UnityEngine;
namespace Leguar.TotalJSON {
/// <summary>
/// Settings that can be used to make output of creating JSON-formatted string different.
/// </summary>
public class CreateStringSettings {
private bool escapeForwardSlashes = false;
/// <summary>
/// Sets forward slashes to escaped or not. TotalJSON default is false since escaped forward slashes could cause problems if included to C# code.
/// However, if resulting JSON string is included to for example HTML or JavaScript, it is better to set forward slash escaping on.
/// </summary>
/// <value>
/// True to escape forward slashes ("\/"), false to not ("/").
/// </value>
public bool EscapeForwardSlashes {
set {
escapeForwardSlashes = value;
}
get {
return escapeForwardSlashes;
}
}
private bool humanReadable = false;
/// <summary>
/// Sets output to be more human readable. Linefeeds and indentations are added to output to make it easier for humans to read and edit.
/// Output is still completely valid JSON that can be parsed back to JSON or JArray object.
/// </summary>
/// <value>
/// True to make output human readable. Default is false.
/// </value>
public bool HumanReadable {
set {
humanReadable = value;
}
get {
return humanReadable;
}
}
private bool indentUsingTab = true;
/// <summary>
/// Sets whatever indent of human readable output should use tabs. If false, spaces are used instead of tab.
/// </summary>
/// <remarks>
/// This setting have effect only if 'HumanReadable' is true.
/// </remarks>
/// <value>
/// True to use tabs for indent. Default is true.
/// </value>
public bool IndentUsingTab {
set {
if (!humanReadable) {
Debug.LogWarning("CreateStringSettings.IndentUsingTab setting have no effect when CreateStringSettings.HumanReadable is false");
}
indentUsingTab = value;
}
get {
return indentUsingTab;
}
}
private int indentSpaceCount = 4;
/// <summary>
/// Sets how many spaces are used for indent. Can be 0 or any positive integer.
/// </summary>
/// <remarks>
/// This setting have effect only if 'HumanReadable' is true and 'IndentUsingTab' is false.
/// </remarks>
/// <value>
/// Amount of spaces to use for indent. Default is 4.
/// </value>
public int IndentSpaceCount {
set {
if (!humanReadable) {
Debug.LogWarning("CreateStringSettings.IndentSpaceCount setting have no effect when CreateStringSettings.HumanReadable is false");
} else if (indentUsingTab) {
Debug.LogWarning("CreateStringSettings.IndentSpaceCount setting have no effect when CreateStringSettings.IndentUsingTab is true");
}
indentSpaceCount = value;
}
get {
return indentSpaceCount;
}
}
public enum NewLineTypes {
EnvironmentDefault,
LF,
CR_LF
}
private NewLineTypes newLine = NewLineTypes.EnvironmentDefault;
/// <summary>
/// Sets type of linefeeds in human readable output.
/// </summary>
/// <remarks>
/// This setting have effect only if 'HumanReadable' is true.
/// </remarks>
/// <value>
/// Type of linefeeds, one of values from NewLineTypes. Default is EnvironmentDefault.
/// </value>
public NewLineTypes NewLine {
set {
if (!humanReadable) {
Debug.LogWarning("CreateStringSettings.NewLine setting have no effect when CreateStringSettings.HumanReadable is false");
}
newLine = value;
}
get {
return newLine;
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: e51ce8bcbc9ee4c4db94a03f8c456c64
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,121 @@
// DeserializeSettings
namespace Leguar.TotalJSON {
/// <summary>
/// Settings for deserialization.
/// </summary>
public class DeserializeSettings {
private bool allowFieldsToBeObjects = false;
/// <summary>
/// By default this is false. Meaning that any fields where values are deserialized need to be exactly same type as JSON object. For example JBoolean goes only to
/// bool, JString goes only to string, JSON goes only to Dictionary etc.
///
/// If this is set true, deserialization allows target fields also to be just objects (System.Object). Note however that in some cases deserialization may need to
/// "guess" the correct type, for example if deserializing JNumber to object field ("10" can be either int, long, float or double).
/// </summary>
/// <value>
/// False by default, set true to allow more loose deserialization.
/// </value>
public bool AllowFieldsToBeObjects {
set {
allowFieldsToBeObjects = value;
}
get {
return allowFieldsToBeObjects;
}
}
private bool allowNonStringDictionaryKeys = false;
/// <summary>
/// By default this is false. Meaning that if any JSON object is deserialized to dictionary, target dictionary must be using string keys, like JSON itself is using.
///
/// If this is set true, dictionaries key type may also be integer or long. In this case deserialization try to change JSON keys to required dictionary key type.
/// Note however that this may cause several problems when deserializing. For example, JSON object may contain keys "1" and "01". Deserializing this to Dictionary
/// with string keys can be done without issues. But deserializing that JSON to Dictionary with integer keys causes error due duplicate key, even original JSON is
/// completely valid.
/// </summary>
/// <value>
/// False by default, set true to allow more loose and flexible deserialization to dictionaries.
/// </value>
public bool AllowNonStringDictionaryKeys {
set {
allowNonStringDictionaryKeys = value;
}
get {
return allowNonStringDictionaryKeys;
}
}
private bool ignoreSystemAndUnitySerializeAttributes = false;
/// <summary>
/// By default this is false. Meaning that deserialization will check fields for UnityEngine.SerializeField and System.NonSerialized attributes and follow those.
///
/// In case these attributes are required for other uses but JSON deserialization should not follow these attributes, you can set this setting to true and those
/// attributes will be ignored during JSON deserialization. You can still include/exclude single fields during deserialization using TotalJSON's own
/// IncludeToJSONSerialize and ExcludeFromJSONSerialize attributes which are always followed regardless of this setting.
/// </summary>
/// <value>
/// False by default, set true to ignore non-json specific serialization attributes.
/// </value>
public bool IgnoreSystemAndUnitySerializeAttributes {
set {
ignoreSystemAndUnitySerializeAttributes = value;
}
get {
return ignoreSystemAndUnitySerializeAttributes;
}
}
private bool requireAllFieldsArePopulated = true;
/// <summary>
/// Default is true, meaning all the public fields in class/struct where JSON is deserialized must get their value set. So source JSON must contain matching values
/// for all the fields.
///
/// If set to false, fields that have no matching data in JSON are just left in their default values.
///
/// For example, with default setting, deserializing JSON {"a":1,"b":2} to class { public int a; public int b; public int c; } will cause exception since there's
/// no value for field 'c'.
/// </summary>
/// <value>
/// True by default, set false to allow classes/structs not to get fully populated.
/// </value>
public bool RequireAllFieldsArePopulated {
set {
requireAllFieldsArePopulated = value;
}
get {
return requireAllFieldsArePopulated;
}
}
private bool requireAllJSONValuesAreUsed = false;
/// <summary>
/// Default is false, meaning that any possible extra values in source JSON are ignored. If set to true, it is strictly required that all the values from JSON must
/// get used to populate some field in target class/struct.
///
/// For example, with default setting, deserializing JSON {"a":1,"b":2,"c":3} to class { public int a; public int b; } is acceptable and JSON value for 'c' is just
/// not used.
/// </summary>
/// <value>
/// False by default, set true to require that everything in source JSON is used.
/// </value>
public bool RequireAllJSONValuesAreUsed {
set {
requireAllJSONValuesAreUsed = value;
}
get {
return requireAllJSONValuesAreUsed;
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: 75df3196b7ff7f146a45b3bea4f17153
timeCreated: 1575388796
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,95 @@
// ParseStringSettings
using System;
using UnityEngine;
namespace Leguar.TotalJSON {
/// <summary>
/// Settings that can be used to make changes how string is parsed to JSON or JArray.
/// </summary>
public class ParseStringSettings {
private bool fixRoundedFloatingPointMinMaxValues = true;
/// <summary>
/// If set true, numeric values that seem to be just rounded float.MinValue, float.MaxValue, double.MinValue or double.MaxValue are set to those exact values.
///
/// C# floating point numbers rounding sometimes causes unwanted effects. In some systems, for example double.Parse(double.MaxValue.ToString()) will cause number overflow exception.
/// TotalJSON will use exact values when creating JSON formatted string using CreateString() method. But if JSON is created using other methods and it is possible JSON may contain
/// rounded floating point min/max values, it is better to set this setting true so that parsed values are what they are expected to be.
/// </summary>
/// <value>
/// True to fix rounded floating point values to float/double min/max values. False to parse numbers exactly as they are. Default is true.
/// </value>
public bool FixRoundedFloatingPointMinMaxValues {
set {
fixRoundedFloatingPointMinMaxValues = value;
}
get {
return fixRoundedFloatingPointMinMaxValues;
}
}
private int parseStartIndex = 0;
/// <summary>
/// Sets index of input string where parsing JSON or JArray object is started.
/// </summary>
/// <value>
/// The index of the parse start. Default is 0.
/// </value>
public int ParseStartIndex {
set {
parseStartIndex = value;
}
get {
return parseStartIndex;
}
}
private bool allowNonWhiteCharactersAfterObject = false;
/// <summary>
/// Sets whatever it is acceptable for input string to have other than non-white characters after end of JSON or JArray object.
/// </summary>
/// <value>
/// If set to true, non-white characters are accepted at end of object. Default is false, so expecting that input string ends at the end of JSON or JArray object.
/// </value>
public bool AllowNonWhiteCharactersAfterObject {
set {
allowNonWhiteCharactersAfterObject = value;
}
get {
return allowNonWhiteCharactersAfterObject;
}
}
private string debugIDForExceptions = null;
/// <summary>
/// Sets debug ID for this string parse and resulting JSON object. If any exception occurres during parsing or JSON handling after
/// succesful parse, this debug ID will be added to exception message.
///
/// This is typically useful in production builds where only exception message is logged but full stacktrace may not be available.
/// Typical parse error could be that source string is null or empty for some reason. Without adding this debug id to the parse,
/// exception is just "ParseException: Source string is empty" which isn't very helpful if project is parsing lots of incoming JSON
/// and so it is not clear which one causes this error. When adding this debug id to the parse, above exception would be for example
/// "ParseException: Source string is empty - Parse Debug ID: Backend own currency settings", which pinpoints the problem instantly.
/// </summary>
/// <value>
/// Debug ID. Default is null.
/// </value>
public string DebugIDForExceptions {
set {
debugIDForExceptions = value;
}
get {
return debugIDForExceptions;
}
}
}
}

View File

@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: cef3164b1a677324f831ad8b0c509a49
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,54 @@
// SerializeSettings
namespace Leguar.TotalJSON {
/// <summary>
/// Settings for serialization.
/// </summary>
public class SerializeSettings {
private bool allowNonStringDictionaryKeys = false;
/// <summary>
/// By default this is false. Meaning that if any dictionary is serialized to JSON object, source dictionary must be using string keys, like JSON itself is using.
///
/// If this is set false, dictionaries key type may be anything and serialization is just using ToString() to create key. In this case, make sure each dictionary
/// key string representation is unique.
/// </summary>
/// <value>
/// False by default, set true to allow any dictionary keys.
/// </value>
public bool AllowNonStringDictionaryKeys {
set {
allowNonStringDictionaryKeys = value;
}
get {
return allowNonStringDictionaryKeys;
}
}
private bool ignoreSystemAndUnitySerializeAttributes = false;
/// <summary>
/// By default this is false. Meaning that serialization will check fields for UnityEngine.SerializeField and System.NonSerialized attributes and follow those.
///
/// In case these attributes are required for other uses but JSON serialization should not follow these attributes, you can set this setting to true and those
/// attributes will be ignored during JSON serialization. You can still include/exclude single fields from serialization using TotalJSON's own
/// IncludeToJSONSerialize and ExcludeFromJSONSerialize attributes which are always followed regardless of this setting.
/// </summary>
/// <value>
/// False by default, set true to ignore non-json specific serialization attributes.
/// </value>
public bool IgnoreSystemAndUnitySerializeAttributes {
set {
ignoreSystemAndUnitySerializeAttributes = value;
}
get {
return ignoreSystemAndUnitySerializeAttributes;
}
}
}
}

View File

@@ -0,0 +1,12 @@
fileFormatVersion: 2
guid: a0a1c7d8f21e2f24bbf40192a47ff82a
timeCreated: 1575455464
licenseType: Store
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: