블로그 이미지
Every unexpected event is a path to learning for you. blueasa

카테고리

분류 전체보기 (2795)
Unity3D (852)
Programming (478)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (185)
협업 (61)
3DS Max (3)
Game (12)
Utility (68)
Etc (98)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (55)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday

Restful API로 플랫폼간 연동을 하는 일들이 많다보니, Json 라이브러리는 필수라서 정보를 찾아 본 것을 정리.

우선 http://json.org/json-ko.html 에 정리되어 있는 C# 라이브러리를 먼저 보면

이 중에서 유니티 개발자 그룹 같은데서 많이 보이는 라이브러는 LitJson과 JsonFx..

* LitJson : http://lbv.github.io/litjson
이 라이브러를 추천하는 경우가 많은데, 다른 라이브러리들과 마찬가지로 iOS에서 serialize 문제가 있는 듯.

해결법 , http://forum.unity3d.com/threads/litjson-issue-on-ios.113181/ 참고.

* JsonFx : https://github.com/jsonfx/jsonfx
LitJson의 iOS 문제를 JsonFx를 사용해서 해결했다는 글이 보이길래 찾아봤는데,
Github에 올라온 패키지가 2년전 것. 물론 단순한 구조인 json 특성 상 딱히 건드릴만한 것이 없긴 하지만, 좀 써보고 판단을 해야 할듯.


[출처]

https://heartgamer.wordpress.com/2015/01/10/unity%EC%97%90%EC%84%9C-json-%EC%82%AC%EC%9A%A9-%EC%8B%9C-%EA%B3%A0%EB%A0%A4%ED%95%A0-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC/

반응형

'Programming > JSON' 카테고리의 다른 글

[펌] Excel 데이터를 Json으로 변환하기  (0) 2016.08.08
[펌] SimpleJSON  (0) 2016.08.08
Convert Excel to JSON  (0) 2014.03.04
Posted by blueasa
, |

[펌] SimpleJSON

Programming/JSON / 2016. 8. 8. 10:21

SimpleJSON


Contents

 [hide

Description

SimpleJSON is an easy to use JSON parser and builder. It uses strong typed classes for the different JSONTypes. The parser / builder does not distinguish between different value types. Number, boolean and null will be treated like strings. This might cause problems when you need to build a JSON string that requires the actual types.

In short: The parser conforms to rfc4627, the generator does not.


I've updated (only) the source code embedded in the page, and it now appears to round-trip, although this isn't particularly well tested and it's a very naive implementation. Use .ToJSON(0) to use the round-trip version. -- Opless (talk) 22:39, 21 September 2014 (CEST)OPless

Usage

To use SimpleJSON in Unity you just have to copy the SimpleJSON.cs file into your projects "plugins" folder inside your assets folder.

If you want to use the compression feature when it comes to saving and loading you have to download the SharpZipLib assembly and place it next to the SimpleJSON.cs file. In addition you have to uncomment the define at the top of the SimpleJSON.cs file.

For language specific usage see below.

CSharp

Like most assemblies SimpleJSON is contained in its own namespace to avoid name collisions.

To use SimpleJSON in C# you have to add this line at the top of your script:

using SimpleJSON;

UnityScript (Unity's Javascript)

To use SimpleJSON in UnityScript you have to add this line at the top of your script:

import SimpleJSON;

For UnityScript it's vital to place the SimpleJSON.cs (and SharpZipLib if needed) into a higher compilation group than the UnityScript file that should use it. The usual place is the Plugins folder which should work in most cases.

Examples (C# / UnityScript)

This is the JSON string which will be used in this example:

{
    "version": "1.0",
    "data": {
        "sampleArray": [
            "string value",
            5,
            {
                "name": "sub object"
            }
        ]
    }
}


var N = JSON.Parse(the_JSON_string);
var versionString = N["version"].Value;        // versionString will be a string containing "1.0"
var versionNumber = N["version"].AsFloat;      // versionNumber will be a float containing 1.0
var name = N["data"]["sampleArray"][2]["name"];// name will be a string containing "sub object"
 
//C#
string val = N["data"]["sampleArray"][0];      // val contains "string value"
 
//UnityScript
var val : String = N["data"]["sampleArray"][0];// val contains "string value"
 
var i = N["data"]["sampleArray"][1].AsInt;     // i will be an integer containing 5
N["data"]["sampleArray"][1].AsInt = i+6;       // the second value in sampleArray will contain "11"
 
N["additional"]["second"]["name"] = "FooBar";  // this will create a new object named "additional" in this object create another
                                               //object "second" in this object add a string variable "name"
 
var mCount = N["countries"]["germany"]["moronCount"].AsInt; // this will return 0 and create all the required objects and
                                                            // initialize "moronCount" with 0.
 
if (N["wrong"] != null)                        // this won't execute the if-statement since "wrong" doesn't exist
{}
if (N["wrong"].AsInt == 0)                     // this will execute the if-statement and in addition add the "wrong" value.
{}
 
N["data"]["sampleArray"][-1] = "Test";         // this will add another string to the end of the array
N["data"]["sampleArray"][-1]["name"] = "FooBar"; // this will add another object to the end of the array which contains a string named "name"
 
N["data"] = "erased";                          // this will replace the object stored in data with the string "erased"


Download

Here's the whole thing packed as unityPackage and as seperate files including example / test scripts

Media:SimpleJSON.zip


SimpleJSON.cs

//#define USE_SharpZipLib
#if !UNITY_WEBPLAYER
#define USE_FileIO
#endif
/* * * * *
 * A simple JSON Parser / builder
 * ------------------------------
 * 
 * It mainly has been written as a simple JSON parser. It can build a JSON string
 * from the node-tree, or generate a node tree from any valid JSON string.
 * 
 * If you want to use compression when saving to file / stream / B64 you have to include
 * SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ ) in your project and
 * define "USE_SharpZipLib" at the top of the file
 * 
 * Written by Bunny83 
 * 2012-06-09
 * 
 * Modified by oPless, 2014-09-21 to round-trip properly
 *
 * Features / attributes:
 * - provides strongly typed node classes and lists / dictionaries
 * - provides easy access to class members / array items / data values
 * - the parser ignores data types. Each value is a string.
 * - only double quotes (") are used for quoting strings.
 * - values and names are not restricted to quoted strings. They simply add up and are trimmed.
 * - There are only 3 types: arrays(JSONArray), objects(JSONClass) and values(JSONData)
 * - provides "casting" properties to easily convert to / from those types:
 *   int / float / double / bool
 * - provides a common interface for each node so no explicit casting is required.
 * - the parser try to avoid errors, but if malformed JSON is parsed the result is undefined
 * 
 * 
 * 2012-12-17 Update:
 * - Added internal JSONLazyCreator class which simplifies the construction of a JSON tree
 *   Now you can simple reference any item that doesn't exist yet and it will return a JSONLazyCreator
 *   The class determines the required type by it's further use, creates the type and removes itself.
 * - Added binary serialization / deserialization.
 * - Added support for BZip2 zipped binary format. Requires the SharpZipLib ( http://www.icsharpcode.net/opensource/sharpziplib/ )
 *   The usage of the SharpZipLib library can be disabled by removing or commenting out the USE_SharpZipLib define at the top
 * - The serializer uses different types when it comes to store the values. Since my data values
 *   are all of type string, the serializer will "try" which format fits best. The order is: int, float, double, bool, string.
 *   It's not the most efficient way but for a moderate amount of data it should work on all platforms.
 * 
 * * * * */
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
 
 
namespace SimpleJSON
{
	public enum JSONBinaryTag
	{
		Array = 1,
		Class = 2,
		Value = 3,
		IntValue = 4,
		DoubleValue = 5,
		BoolValue = 6,
		FloatValue = 7,
	}
 
	public abstract class JSONNode
	{
		#region common interface
 
		public virtual void Add (string aKey, JSONNode aItem)
		{
		}
 
		public virtual JSONNode this [int aIndex]   { get { return null; } set { } }
 
		public virtual JSONNode this [string aKey]  { get { return null; } set { } }
 
		public virtual string Value                { get { return ""; } set { } }
 
		public virtual int Count                   { get { return 0; } }
 
		public virtual void Add (JSONNode aItem)
		{
			Add ("", aItem);
		}
 
		public virtual JSONNode Remove (string aKey)
		{
			return null;
		}
 
		public virtual JSONNode Remove (int aIndex)
		{
			return null;
		}
 
		public virtual JSONNode Remove (JSONNode aNode)
		{
			return aNode;
		}
 
		public virtual IEnumerable<JSONNode> Children
		{
			get {
				yield break;
			}
		}
 
		public IEnumerable<JSONNode> DeepChildren
		{
			get {
				foreach (var C in Children)
					foreach (var D in C.DeepChildren)
						yield return D;
			}
		}
 
		public override string ToString ()
		{
			return "JSONNode";
		}
 
		public virtual string ToString (string aPrefix)
		{
			return "JSONNode";
		}
 
		public abstract string ToJSON (int prefix);
 
		#endregion common interface
 
		#region typecasting properties
 
		public virtual JSONBinaryTag Tag { get; set; }
 
		public virtual int AsInt
		{
			get {
				int v = 0;
				if (int.TryParse (Value, out v))
					return v;
				return 0;
			}
			set {
				Value = value.ToString ();
				Tag = JSONBinaryTag.IntValue;
			}
		}
 
		public virtual float AsFloat
		{
			get {
				float v = 0.0f;
				if (float.TryParse (Value, out v))
					return v;
				return 0.0f;
			}
			set {
				Value = value.ToString ();
				Tag = JSONBinaryTag.FloatValue;
			}
		}
 
		public virtual double AsDouble
		{
			get {
				double v = 0.0;
				if (double.TryParse (Value, out v))
					return v;
				return 0.0;
			}
			set {
				Value = value.ToString ();
				Tag = JSONBinaryTag.DoubleValue;
 
			}
		}
 
		public virtual bool AsBool
		{
			get {
				bool v = false;
				if (bool.TryParse (Value, out v))
					return v;
				return !string.IsNullOrEmpty (Value);
			}
			set {
				Value = (value) ? "true" : "false";
				Tag = JSONBinaryTag.BoolValue;
 
			}
		}
 
		public virtual JSONArray AsArray
		{
			get {
				return this as JSONArray;
			}
		}
 
		public virtual JSONClass AsObject
		{
			get {
				return this as JSONClass;
			}
		}
 
 
		#endregion typecasting properties
 
		#region operators
 
		public static implicit operator JSONNode (string s)
		{
			return new JSONData (s);
		}
 
		public static implicit operator string (JSONNode d)
		{
			return (d == null) ? null : d.Value;
		}
 
		public static bool operator == (JSONNode a, object b)
		{
			if (b == null && a is JSONLazyCreator)
				return true;
			return System.Object.ReferenceEquals (a, b);
		}
 
		public static bool operator != (JSONNode a, object b)
		{
			return !(a == b);
		}
 
		public override bool Equals (object obj)
		{
			return System.Object.ReferenceEquals (this, obj);
		}
 
		public override int GetHashCode ()
		{
			return base.GetHashCode ();
		}
 
 
		#endregion operators
 
		internal static string Escape (string aText)
		{
			string result = "";
			foreach (char c in aText) {
				switch (c) {
					case '\\':
						result += "\\\\";
						break;
					case '\"':
						result += "\\\"";
						break;
					case '\n':
						result += "\\n";
						break;
					case '\r':
						result += "\\r";
						break;
					case '\t':
						result += "\\t";
						break;
					case '\b':
						result += "\\b";
						break;
					case '\f':
						result += "\\f";
						break;
					default   :
						result += c;
						break;
				}
			}
			return result;
		}
 
		static JSONData Numberize (string token)
		{
			bool flag = false;
			int integer = 0;
			double real = 0;
 
			if (int.TryParse (token, out integer)) {
				return new JSONData (integer);
			}
 
			if (double.TryParse (token, out real)) {
				return new JSONData (real);
			}
 
			if (bool.TryParse (token, out flag)) {
				return new JSONData (flag);
			}
 
			throw new NotImplementedException (token);
		}
 
		static void AddElement (JSONNode ctx, string token, string tokenName, bool tokenIsString)
		{
			if (tokenIsString) {
				if (ctx is JSONArray)
					ctx.Add (token);
				else
					ctx.Add (tokenName, token); // assume dictionary/object
			} else {
				JSONData number = Numberize (token);
				if (ctx is JSONArray)
					ctx.Add (number);
				else
					ctx.Add (tokenName, number);
 
			}
		}
 
		public static JSONNode Parse (string aJSON)
		{
			Stack<JSONNode> stack = new Stack<JSONNode> ();
			JSONNode ctx = null;
			int i = 0;
			string Token = "";
			string TokenName = "";
			bool QuoteMode = false;
			bool TokenIsString = false;
			while (i < aJSON.Length) {
				switch (aJSON [i]) {
					case '{':
						if (QuoteMode) {
							Token += aJSON [i];
							break;
						}
						stack.Push (new JSONClass ());
						if (ctx != null) {
							TokenName = TokenName.Trim ();
							if (ctx is JSONArray)
								ctx.Add (stack.Peek ());
							else if (TokenName != "")
								ctx.Add (TokenName, stack.Peek ());
						}
						TokenName = "";
						Token = "";
						ctx = stack.Peek ();
						break;
 
					case '[':
						if (QuoteMode) {
							Token += aJSON [i];
							break;
						}
 
						stack.Push (new JSONArray ());
						if (ctx != null) {
							TokenName = TokenName.Trim ();
 
							if (ctx is JSONArray)
								ctx.Add (stack.Peek ());
							else if (TokenName != "")
								ctx.Add (TokenName, stack.Peek ());
						}
						TokenName = "";
						Token = "";
						ctx = stack.Peek ();
						break;
 
					case '}':
					case ']':
						if (QuoteMode) {
							Token += aJSON [i];
							break;
						}
						if (stack.Count == 0)
							throw new Exception ("JSON Parse: Too many closing brackets");
 
						stack.Pop ();
						if (Token != "") {
							TokenName = TokenName.Trim ();
							/*
							if (ctx is JSONArray)
								ctx.Add (Token);
							else if (TokenName != "")
								ctx.Add (TokenName, Token);
								*/
							AddElement (ctx, Token, TokenName, TokenIsString);
							TokenIsString = false;
						}
						TokenName = "";
						Token = "";
						if (stack.Count > 0)
							ctx = stack.Peek ();
						break;
 
					case ':':
						if (QuoteMode) {
							Token += aJSON [i];
							break;
						}
						TokenName = Token;
						Token = "";
						TokenIsString = false;
						break;
 
					case '"':
						QuoteMode ^= true;
						TokenIsString = QuoteMode == true ? true : TokenIsString;
						break;
 
					case ',':
						if (QuoteMode) {
							Token += aJSON [i];
							break;
						}
						if (Token != "") {
							/*
							if (ctx is JSONArray) {
								ctx.Add (Token);
							} else if (TokenName != "") {
								ctx.Add (TokenName, Token);
							}
							*/
							AddElement (ctx, Token, TokenName, TokenIsString);
							TokenIsString = false;
 
						}
						TokenName = "";
						Token = "";
						TokenIsString = false;
						break;
 
					case '\r':
					case '\n':
						break;
 
					case ' ':
					case '\t':
						if (QuoteMode)
							Token += aJSON [i];
						break;
 
					case '\\':
						++i;
						if (QuoteMode) {
							char C = aJSON [i];
							switch (C) {
								case 't':
									Token += '\t';
									break;
								case 'r':
									Token += '\r';
									break;
								case 'n':
									Token += '\n';
									break;
								case 'b':
									Token += '\b';
									break;
								case 'f':
									Token += '\f';
									break;
								case 'u':
									{
										string s = aJSON.Substring (i + 1, 4);
										Token += (char)int.Parse (
											s,
											System.Globalization.NumberStyles.AllowHexSpecifier);
										i += 4;
										break;
									}
								default  :
									Token += C;
									break;
							}
						}
						break;
 
					default:
						Token += aJSON [i];
						break;
				}
				++i;
			}
			if (QuoteMode) {
				throw new Exception ("JSON Parse: Quotation marks seems to be messed up.");
			}
			return ctx;
		}
 
		public virtual void Serialize (System.IO.BinaryWriter aWriter)
		{
		}
 
		public void SaveToStream (System.IO.Stream aData)
		{
			var W = new System.IO.BinaryWriter (aData);
			Serialize (W);
		}
 
		#if USE_SharpZipLib
		public void SaveToCompressedStream(System.IO.Stream aData)
		{
			using (var gzipOut = new ICSharpCode.SharpZipLib.BZip2.BZip2OutputStream(aData))
			{
				gzipOut.IsStreamOwner = false;
				SaveToStream(gzipOut);
				gzipOut.Close();
			}
		}
 
		public void SaveToCompressedFile(string aFileName)
		{
 
#if USE_FileIO
			System.IO.Directory.CreateDirectory((new System.IO.FileInfo(aFileName)).Directory.FullName);
			using(var F = System.IO.File.OpenWrite(aFileName))
			{
				SaveToCompressedStream(F);
			}
 
#else
			throw new Exception("Can't use File IO stuff in webplayer");
#endif
		}
		public string SaveToCompressedBase64()
		{
			using (var stream = new System.IO.MemoryStream())
			{
				SaveToCompressedStream(stream);
				stream.Position = 0;
				return System.Convert.ToBase64String(stream.ToArray());
			}
		}
 
#else
		public void SaveToCompressedStream (System.IO.Stream aData)
		{
			throw new Exception ("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
		}
 
		public void SaveToCompressedFile (string aFileName)
		{
			throw new Exception ("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
		}
 
		public string SaveToCompressedBase64 ()
		{
			throw new Exception ("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
		}
		#endif
 
		public void SaveToFile (string aFileName)
		{
#if USE_FileIO
			System.IO.Directory.CreateDirectory ((new System.IO.FileInfo (aFileName)).Directory.FullName);
			using (var F = System.IO.File.OpenWrite (aFileName)) {
				SaveToStream (F);
			}
			#else
			throw new Exception ("Can't use File IO stuff in webplayer");
			#endif
		}
 
		public string SaveToBase64 ()
		{
			using (var stream = new System.IO.MemoryStream ()) {
				SaveToStream (stream);
				stream.Position = 0;
				return System.Convert.ToBase64String (stream.ToArray ());
			}
		}
 
		public static JSONNode Deserialize (System.IO.BinaryReader aReader)
		{
			JSONBinaryTag type = (JSONBinaryTag)aReader.ReadByte ();
			switch (type) {
				case JSONBinaryTag.Array:
					{
						int count = aReader.ReadInt32 ();
						JSONArray tmp = new JSONArray ();
						for (int i = 0; i < count; i++)
							tmp.Add (Deserialize (aReader));
						return tmp;
					}
				case JSONBinaryTag.Class:
					{
						int count = aReader.ReadInt32 ();                
						JSONClass tmp = new JSONClass ();
						for (int i = 0; i < count; i++) {
							string key = aReader.ReadString ();
							var val = Deserialize (aReader);
							tmp.Add (key, val);
						}
						return tmp;
					}
				case JSONBinaryTag.Value:
					{
						return new JSONData (aReader.ReadString ());
					}
				case JSONBinaryTag.IntValue:
					{
						return new JSONData (aReader.ReadInt32 ());
					}
				case JSONBinaryTag.DoubleValue:
					{
						return new JSONData (aReader.ReadDouble ());
					}
				case JSONBinaryTag.BoolValue:
					{
						return new JSONData (aReader.ReadBoolean ());
					}
				case JSONBinaryTag.FloatValue:
					{
						return new JSONData (aReader.ReadSingle ());
					}
 
				default:
					{
						throw new Exception ("Error deserializing JSON. Unknown tag: " + type);
					}
			}
		}
 
		#if USE_SharpZipLib
		public static JSONNode LoadFromCompressedStream(System.IO.Stream aData)
		{
			var zin = new ICSharpCode.SharpZipLib.BZip2.BZip2InputStream(aData);
			return LoadFromStream(zin);
		}
		public static JSONNode LoadFromCompressedFile(string aFileName)
		{
#if USE_FileIO
			using(var F = System.IO.File.OpenRead(aFileName))
			{
				return LoadFromCompressedStream(F);
			}
#else
			throw new Exception("Can't use File IO stuff in webplayer");
#endif
		}
		public static JSONNode LoadFromCompressedBase64(string aBase64)
		{
			var tmp = System.Convert.FromBase64String(aBase64);
			var stream = new System.IO.MemoryStream(tmp);
			stream.Position = 0;
			return LoadFromCompressedStream(stream);
		}
#else
		public static JSONNode LoadFromCompressedFile (string aFileName)
		{
			throw new Exception ("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
		}
 
		public static JSONNode LoadFromCompressedStream (System.IO.Stream aData)
		{
			throw new Exception ("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
		}
 
		public static JSONNode LoadFromCompressedBase64 (string aBase64)
		{
			throw new Exception ("Can't use compressed functions. You need include the SharpZipLib and uncomment the define at the top of SimpleJSON");
		}
		#endif
 
		public static JSONNode LoadFromStream (System.IO.Stream aData)
		{
			using (var R = new System.IO.BinaryReader (aData)) {
				return Deserialize (R);
			}
		}
 
		public static JSONNode LoadFromFile (string aFileName)
		{
			#if USE_FileIO
			using (var F = System.IO.File.OpenRead (aFileName)) {
				return LoadFromStream (F);
			}
			#else
			throw new Exception ("Can't use File IO stuff in webplayer");
			#endif
		}
 
		public static JSONNode LoadFromBase64 (string aBase64)
		{
			var tmp = System.Convert.FromBase64String (aBase64);
			var stream = new System.IO.MemoryStream (tmp);
			stream.Position = 0;
			return LoadFromStream (stream);
		}
	}
	// End of JSONNode
 
	public class JSONArray : JSONNode, IEnumerable
	{
		private List<JSONNode> m_List = new List<JSONNode> ();
 
		public override JSONNode this [int aIndex]
		{
			get {
				if (aIndex < 0 || aIndex >= m_List.Count)
					return new JSONLazyCreator (this);
				return m_List [aIndex];
			}
			set {
				if (aIndex < 0 || aIndex >= m_List.Count)
					m_List.Add (value);
				else
					m_List [aIndex] = value;
			}
		}
 
		public override JSONNode this [string aKey]
		{
			get{ return new JSONLazyCreator (this); }
			set{ m_List.Add (value); }
		}
 
		public override int Count
		{
			get { return m_List.Count; }
		}
 
		public override void Add (string aKey, JSONNode aItem)
		{
			m_List.Add (aItem);
		}
 
		public override JSONNode Remove (int aIndex)
		{
			if (aIndex < 0 || aIndex >= m_List.Count)
				return null;
			JSONNode tmp = m_List [aIndex];
			m_List.RemoveAt (aIndex);
			return tmp;
		}
 
		public override JSONNode Remove (JSONNode aNode)
		{
			m_List.Remove (aNode);
			return aNode;
		}
 
		public override IEnumerable<JSONNode> Children
		{
			get {
				foreach (JSONNode N in m_List)
					yield return N;
			}
		}
 
		public IEnumerator GetEnumerator ()
		{
			foreach (JSONNode N in m_List)
				yield return N;
		}
 
		public override string ToString ()
		{
			string result = "[ ";
			foreach (JSONNode N in m_List) {
				if (result.Length > 2)
					result += ", ";
				result += N.ToString ();
			}
			result += " ]";
			return result;
		}
 
		public override string ToString (string aPrefix)
		{
			string result = "[ ";
			foreach (JSONNode N in m_List) {
				if (result.Length > 3)
					result += ", ";
				result += "\n" + aPrefix + "   ";                
				result += N.ToString (aPrefix + "   ");
			}
			result += "\n" + aPrefix + "]";
			return result;
		}
 
		public override string ToJSON (int prefix)
		{
			string s = new string (' ', (prefix + 1) * 2);
			string ret = "[ ";
			foreach (JSONNode n in m_List) {
				if (ret.Length > 3)
					ret += ", ";
				ret += "\n" + s;
				ret += n.ToJSON (prefix + 1);
 
			}
			ret += "\n" + s + "]";
			return ret;
		}
 
		public override void Serialize (System.IO.BinaryWriter aWriter)
		{
			aWriter.Write ((byte)JSONBinaryTag.Array);
			aWriter.Write (m_List.Count);
			for (int i = 0; i < m_List.Count; i++) {
				m_List [i].Serialize (aWriter);
			}
		}
	}
	// End of JSONArray
 
	public class JSONClass : JSONNode, IEnumerable
	{
		private Dictionary<string,JSONNode> m_Dict = new Dictionary<string,JSONNode> ();
 
		public override JSONNode this [string aKey]
		{
			get {
				if (m_Dict.ContainsKey (aKey))
					return m_Dict [aKey];
				else
					return new JSONLazyCreator (this, aKey);
			}
			set {
				if (m_Dict.ContainsKey (aKey))
					m_Dict [aKey] = value;
				else
					m_Dict.Add (aKey, value);
			}
		}
 
		public override JSONNode this [int aIndex]
		{
			get {
				if (aIndex < 0 || aIndex >= m_Dict.Count)
					return null;
				return m_Dict.ElementAt (aIndex).Value;
			}
			set {
				if (aIndex < 0 || aIndex >= m_Dict.Count)
					return;
				string key = m_Dict.ElementAt (aIndex).Key;
				m_Dict [key] = value;
			}
		}
 
		public override int Count
		{
			get { return m_Dict.Count; }
		}
 
 
		public override void Add (string aKey, JSONNode aItem)
		{
			if (!string.IsNullOrEmpty (aKey)) {
				if (m_Dict.ContainsKey (aKey))
					m_Dict [aKey] = aItem;
				else
					m_Dict.Add (aKey, aItem);
			} else
				m_Dict.Add (Guid.NewGuid ().ToString (), aItem);
		}
 
		public override JSONNode Remove (string aKey)
		{
			if (!m_Dict.ContainsKey (aKey))
				return null;
			JSONNode tmp = m_Dict [aKey];
			m_Dict.Remove (aKey);
			return tmp;        
		}
 
		public override JSONNode Remove (int aIndex)
		{
			if (aIndex < 0 || aIndex >= m_Dict.Count)
				return null;
			var item = m_Dict.ElementAt (aIndex);
			m_Dict.Remove (item.Key);
			return item.Value;
		}
 
		public override JSONNode Remove (JSONNode aNode)
		{
			try {
				var item = m_Dict.Where (k => k.Value == aNode).First ();
				m_Dict.Remove (item.Key);
				return aNode;
			} catch {
				return null;
			}
		}
 
		public override IEnumerable<JSONNode> Children
		{
			get {
				foreach (KeyValuePair<string,JSONNode> N in m_Dict)
					yield return N.Value;
			}
		}
 
		public IEnumerator GetEnumerator ()
		{
			foreach (KeyValuePair<string, JSONNode> N in m_Dict)
				yield return N;
		}
 
		public override string ToString ()
		{
			string result = "{";
			foreach (KeyValuePair<string, JSONNode> N in m_Dict) {
				if (result.Length > 2)
					result += ", ";
				result += "\"" + Escape (N.Key) + "\":" + N.Value.ToString ();
			}
			result += "}";
			return result;
		}
 
		public override string ToString (string aPrefix)
		{
			string result = "{ ";
			foreach (KeyValuePair<string, JSONNode> N in m_Dict) {
				if (result.Length > 3)
					result += ", ";
				result += "\n" + aPrefix + "   ";
				result += "\"" + Escape (N.Key) + "\" : " + N.Value.ToString (aPrefix + "   ");
			}
			result += "\n" + aPrefix + "}";
			return result;
		}
 
		public override string ToJSON (int prefix)
		{
			string s = new string (' ', (prefix + 1) * 2);
			string ret = "{ ";
			foreach (KeyValuePair<string,JSONNode> n in m_Dict) {
				if (ret.Length > 3)
					ret += ", ";
				ret += "\n" + s;
				ret += string.Format ("\"{0}\": {1}", n.Key, n.Value.ToJSON (prefix + 1));
			}
			ret += "\n" + s + "}";
			return ret;
		}
 
		public override void Serialize (System.IO.BinaryWriter aWriter)
		{
			aWriter.Write ((byte)JSONBinaryTag.Class);
			aWriter.Write (m_Dict.Count);
			foreach (string K in m_Dict.Keys) {
				aWriter.Write (K);
				m_Dict [K].Serialize (aWriter);
			}
		}
	}
	// End of JSONClass
 
	public class JSONData : JSONNode
	{
		private string m_Data;
 
 
		public override string Value
		{
			get { return m_Data; }
			set {
				m_Data = value;
				Tag = JSONBinaryTag.Value;
			}
		}
 
		public JSONData (string aData)
		{
			m_Data = aData;
			Tag = JSONBinaryTag.Value;
		}
 
		public JSONData (float aData)
		{
			AsFloat = aData;
		}
 
		public JSONData (double aData)
		{
			AsDouble = aData;
		}
 
		public JSONData (bool aData)
		{
			AsBool = aData;
		}
 
		public JSONData (int aData)
		{
			AsInt = aData;
		}
 
		public override string ToString ()
		{
			return "\"" + Escape (m_Data) + "\"";
		}
 
		public override string ToString (string aPrefix)
		{
			return "\"" + Escape (m_Data) + "\"";
		}
 
		public override string ToJSON (int prefix)
		{
			switch (Tag) {
				case JSONBinaryTag.DoubleValue:
				case JSONBinaryTag.FloatValue:
				case JSONBinaryTag.IntValue:
					return m_Data;
				case JSONBinaryTag.Value:
					return string.Format ("\"{0}\"", Escape (m_Data));
				default:
					throw new NotSupportedException ("This shouldn't be here: " + Tag.ToString ());
			}
		}
 
		public override void Serialize (System.IO.BinaryWriter aWriter)
		{
			var tmp = new JSONData ("");
 
			tmp.AsInt = AsInt;
			if (tmp.m_Data == this.m_Data) {
				aWriter.Write ((byte)JSONBinaryTag.IntValue);
				aWriter.Write (AsInt);
				return;
			}
			tmp.AsFloat = AsFloat;
			if (tmp.m_Data == this.m_Data) {
				aWriter.Write ((byte)JSONBinaryTag.FloatValue);
				aWriter.Write (AsFloat);
				return;
			}
			tmp.AsDouble = AsDouble;
			if (tmp.m_Data == this.m_Data) {
				aWriter.Write ((byte)JSONBinaryTag.DoubleValue);
				aWriter.Write (AsDouble);
				return;
			}
 
			tmp.AsBool = AsBool;
			if (tmp.m_Data == this.m_Data) {
				aWriter.Write ((byte)JSONBinaryTag.BoolValue);
				aWriter.Write (AsBool);
				return;
			}
			aWriter.Write ((byte)JSONBinaryTag.Value);
			aWriter.Write (m_Data);
		}
	}
	// End of JSONData
 
	internal class JSONLazyCreator : JSONNode
	{
		private JSONNode m_Node = null;
		private string m_Key = null;
 
		public JSONLazyCreator (JSONNode aNode)
		{
			m_Node = aNode;
			m_Key = null;
		}
 
		public JSONLazyCreator (JSONNode aNode, string aKey)
		{
			m_Node = aNode;
			m_Key = aKey;
		}
 
		private void Set (JSONNode aVal)
		{
			if (m_Key == null) {
				m_Node.Add (aVal);
			} else {
				m_Node.Add (m_Key, aVal);
			}
			m_Node = null; // Be GC friendly.
		}
 
		public override JSONNode this [int aIndex]
		{
			get {
				return new JSONLazyCreator (this);
			}
			set {
				var tmp = new JSONArray ();
				tmp.Add (value);
				Set (tmp);
			}
		}
 
		public override JSONNode this [string aKey]
		{
			get {
				return new JSONLazyCreator (this, aKey);
			}
			set {
				var tmp = new JSONClass ();
				tmp.Add (aKey, value);
				Set (tmp);
			}
		}
 
		public override void Add (JSONNode aItem)
		{
			var tmp = new JSONArray ();
			tmp.Add (aItem);
			Set (tmp);
		}
 
		public override void Add (string aKey, JSONNode aItem)
		{
			var tmp = new JSONClass ();
			tmp.Add (aKey, aItem);
			Set (tmp);
		}
 
		public static bool operator == (JSONLazyCreator a, object b)
		{
			if (b == null)
				return true;
			return System.Object.ReferenceEquals (a, b);
		}
 
		public static bool operator != (JSONLazyCreator a, object b)
		{
			return !(a == b);
		}
 
		public override bool Equals (object obj)
		{
			if (obj == null)
				return true;
			return System.Object.ReferenceEquals (this, obj);
		}
 
		public override int GetHashCode ()
		{
			return base.GetHashCode ();
		}
 
		public override string ToString ()
		{
			return "";
		}
 
		public override string ToString (string aPrefix)
		{
			return "";
		}
 
		public override string ToJSON (int prefix)
		{
			return "";
		}
 
		public override int AsInt
		{
			get {
				JSONData tmp = new JSONData (0);
				Set (tmp);
				return 0;
			}
			set {
				JSONData tmp = new JSONData (value);
				Set (tmp);
			}
		}
 
		public override float AsFloat
		{
			get {
				JSONData tmp = new JSONData (0.0f);
				Set (tmp);
				return 0.0f;
			}
			set {
				JSONData tmp = new JSONData (value);
				Set (tmp);
			}
		}
 
		public override double AsDouble
		{
			get {
				JSONData tmp = new JSONData (0.0);
				Set (tmp);
				return 0.0;
			}
			set {
				JSONData tmp = new JSONData (value);
				Set (tmp);
			}
		}
 
		public override bool AsBool
		{
			get {
				JSONData tmp = new JSONData (false);
				Set (tmp);
				return false;
			}
			set {
				JSONData tmp = new JSONData (value);
				Set (tmp);
			}
		}
 
		public override JSONArray AsArray
		{
			get {
				JSONArray tmp = new JSONArray ();
				Set (tmp);
				return tmp;
			}
		}
 
		public override JSONClass AsObject
		{
			get {
				JSONClass tmp = new JSONClass ();
				Set (tmp);
				return tmp;
			}
		}
	}
	// End of JSONLazyCreator
 
	public static class JSON
	{
		public static JSONNode Parse (string aJSON)
		{
			return JSONNode.Parse (aJSON);
		}
	}
}


[출처] http://wiki.unity3d.com/index.php/SimpleJSON#Examples_.28C.23_.2F_UnityScript.29

반응형
Posted by blueasa
, |


[링크] http://edaero.net/917

반응형
Posted by blueasa
, |

[링크] http://blog.naver.com/ian0371/220109191894

반응형
Posted by blueasa
, |


[링크] http://blog.naver.com/aufcl856/220578178180

반응형
Posted by blueasa
, |

출처: http://beatup.springnote.com/pages/3277191


BPM : beat per min 의 준말.  즉 분당 비트수로써 1분당 1/4박자의 갯수이다.

- 1분당 BPM별 비트 갯수

 BPM1/4 박자1/8박자 1/16박자 1/32박자 
 60 BPM 60 개 120 개 240 개 480 개
 100 BPM 100 개 200 개 400 개 800 개
 130 BPM 130 개 260 개 520 개 1040 개
 155 BPM 155 개 310 개 620 개 1240 개


즉, 우리가 만들 게임은 1/32박자 (이하 32비트) 게임이므로
155bpm시 1분당 최대 1240개의 노트가 들어간다.



이제 노트 하나당 간격을 알아보도록 하자.

60bpm에서 4비트는 1초마다 1비트가 올라가므로 최대 60개가 나온다.
그럼 1/8박자는 0.5초마다, 16박자는 0.25초마다, 32박자는 0.125초마다 1비트가 오른다.

130bpm의 32비트는 최대 1040개이므로 비트 하나당 간격을 알아보자.
소수점자리까지 사용하므로 총 8자리까지 쓰고 이하는 반올림을 기준으로 한다.

130 / 60 = 2.16666667
0.125 / 2.1666 = 0.05769230

 


노트는 0.05869230초마다 나오며 이 값이 맞는지 최대 비트인 1040개와 계산을 해보자

 0.05769230 * 1040 = 59.999992


얼추 60이 맞는것을 알수 있다.
더 낮은 자리까지 계산을 하면 정확해지며 이게 정확하지 않다면 음악이 재생시간이
길어질수록 비트는 조금씩 밀리거나 당겨지는 현상이 있을수가 있으므로 주의하기 바란다.


이 문제를 해결하려면 10초마다 실행하는 타이머를 주어 다음 10초간의 비트의 위치를
부분적으로 계산하면 될듯싶다.

60bpm시 부분 계산 방식

 플레이시간읽는 비트 
 0:00 0 - 80 
 0:10 80 - 160
 0:20 160 - 240
 0:30 240 - 320
 0:40 320 - 400
 0:50 400 - 480



화살표(노트) 이동 속도의 구현
60bpm은 매우 느린 속도이다.
120bpm은 60bpm의 2배의 속도이다.
180bpm은 60bpm의 3배의 속도이다. 

 bpm 픽셀당이동속도 
 1 bpm 1 초
 60 bpm 0.00166667 초
 120 bpm 0.00083333 초
 180 bpm 0.00055556 초


픽셀은 구현이 어떤식으로 되는지 모르기에 예를 든것이다.
구현 방법에 따라 적절히 하도록 바람.




 



여기까지 bpm 계산 방법을 알아 보았다.
이제 배속의 구현을 알아보도록 하자.

먼저 bpm 공식에 의거하여 노트는 기본적인 이동속도를 가진다.
이것은 1배속이 된다.

60 bpm이 0.00166667 초에 1픽셀을 이동하는데
만약 2배속일경우엔 0.00083333 초에 1픽셀을 이동한다.

그러나 배속은 비트에 대해 절대 영향을 끼치지 않으며 단순히 이동속도만을 제어한다.



[출처] http://smilejsu.tistory.com/380

반응형
Posted by blueasa
, |

펌 OK (출처 표시), 상업적 이용 NO, 컨텐츠 변경 NO

apk파일을 디컴파일하게되면 원본 소스코드를 100%는 아니더라도 확인이 가능하다.

다만, 소스코드 난독화(proguard등)가 적용되어 있다면 코드의 해석은 상당히 힘들게된다.

그럼에도 불구하고 필요한 소스코드가 있다면 디컴파일하여 쓸만한 건덕지를 찾아봐야하니 디컴파일은 중요하다고

할 수 있다. (개발자의 경우 상당히 기분나쁜부분, 우리는 참고용으로만 사용하자)

디컴파일 전에 몇가지 준비사항이 필요하다.


1. https://code.google.com/p/dex2jar/downloads/list 

여기서 dex2jar 다운로드 > 

C:\Program Files\adt-bundle-windows-x86_64-20130522\sdk\platform-tools\dex2jar-0.0.9.15 경로에 압축해제 

(위 경로는 본인의 경우이고, sdk가 있는 경로상에 집어넣어주면 된다.)

dex2jar.bat 파일 우클릭 후 편집 > echo off 를 echo on 으로 수정



2. http://varaneckas.com/jad/

여기서 최신버전 Jad (자바 디컴파일러) 다운로드 > 압축해제


이제 디컴파일 준비는 끝났다.


시작




- 우선 디컴파일할 apk파일의 확장자를 apk 에서 zip로 바꾸면 zip파일이 된다.

- 압축해제하면 classes.dex 파일이 나온다. 이것만 있으면 된다






그렇게 나온 classes.dex 파일을

아까 받은 dex2jar 폴더로 이동시킨다





그리고 현재 위치의 경로를 복사 한 뒤

시작 > 실행 > cmd > cd적은다음 한칸띄고 마우스 우클릭 > 붙여넣기 > 엔터 하면

위의 경로로 이동





이제 d2j-dex2jar.bat classes.dex를 적고 엔터를 누르면 사진과같이 이상한글이 쫘르륵 나오고

경로에 classes-dex2jar.jar 파일이 생성된다.

버전에 따라 d2j-dex2jar.bat가 아니라 dex2jar.bat 인경우도 있는듯 하니 파일명을 잘보고 알아서 입력한다


그리고 생성된 파일을 압축해제하면 클래스파일들이 나오게 된다.




필자는 proguard를 적용한 apk를 사용했기때문에 보는바와같이 클래스명이 저렇게 지맘대로다.

이제 MainActivity.class를 java파일로 변환해줘야 소스코드를 확인할 수 있다.


MainActivity.class파일을 복사하여 2번에서 설치한 Jad가 설치된 경로에 붙여넣어준다





그리고





다시 시작 > 실행 > cmd > jad 경로로 이동 후


jad -o -sjava MainActivity.class  엔터




그러면 이렇게 MainActivity.java 파일이 생긴다 ! 실행해보자




다시말하지만 필자는 코드난독화(proguard)를 적용했기에 변수명이 이렇게 알아먹기 힘들게 표시된다.

(적용하지 않으면 대부분의 소스코드를 볼 수 있다)

오랜시간 해석한다면 불가능하진 않지만 상당한 곤욕을 치루는것은 어쩔 수 없다.


proguard에 관한 포스팅은 이전글을 참고하길 바라며


-끝-


[출처] http://biig.tistory.com/11

반응형
Posted by blueasa
, |


[링크] http://evir.tistory.com/entry/Unity-Vungle-Plugin-%EC%84%A4%EC%B9%98

반응형
Posted by blueasa
, |


[링크] 

http://evir.tistory.com/entry/Unity-Google-Play-Game-Service-%EC%97%B0%EB%8F%99%EC%8B%9C%ED%82%A4%EA%B8%B0

반응형

'Unity3D > Link' 카테고리의 다른 글

[링크] 캐릭터/애니메이션 판매 사이트(유니티 사용 가능)  (0) 2020.06.18
[Asset] 2D Outline  (0) 2018.05.21
[Link] RhythmTool  (0) 2016.06.21
[Link] Visualizer Studio  (0) 2016.06.21
[Link] Unity 3 Audio Spectrum Analysis  (0) 2016.06.21
Posted by blueasa
, |


[링크] http://evir.tistory.com/entry/Unity-Google-AdMob-Plugin-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0

반응형
Posted by blueasa
, |