Статьи

Понимание JSON

JSON (нотация объектов JavaScript, которую я называю «Jason», и которую вы можете произносить так, как вам нравится) — это текстовый формат данных, разработанный для того, чтобы он был удобочитаемым, легким и простым для передачи между сервером и веб-клиентом. Его синтаксис получен из JavaScript — отсюда и название — но он может использоваться в большинстве языков, включая AS3 и C #.


Если вы много занимались программированием, вы уже сталкивались с массивами: коллекциями элементов, каждому из которых присвоено определенное целое число.

В JSON массив первых шести букв алфавита будет представлен следующим образом:

1
[«a», «b», «c», «d», «e», «f»]

Кодировщики AS3 и JavaScript найдут приведенный выше список очень знакомым. Это похоже на способ определения массива в C #.

Как вы, вероятно, можете догадаться, в квадратных скобках указано «это массив», а запятые используются для разделения различных элементов (обратите внимание, что после последнего элемента запятая отсутствует). Предполагая, что язык, на котором вы анализируете JSON, использует массивы, начинающиеся с нуля (а сколько языков нет в наши дни?), Элемент 0 будет «a», 1 будет «b», 2 будет «c», и так далее.

Чтобы облегчить чтение массивов, мы будем часто писать их с дополнительными символами новой строки и отступами:

1
2
3
4
5
6
7
8
[
    «a»,
    «b»,
    «c»,
    «d»,
    «e»,
    «f»
]

Обратите внимание, что после последнего элемента по-прежнему нет запятой, поэтому теперь она выглядит немного странно.

Нам не нужно использовать строки в качестве элементов массива JSON; мы также можем использовать числа true , false и null . Нет строгой типизации, что означает, что вы можете смешивать типы значений, которые вы используете в любом массиве. Например, это совершенно верно:

01
02
03
04
05
06
07
08
09
10
[
    «apple»,
    3,
    912,
    null,
    -7.2222202,
    «#»,
    true,
    false
]

Обратите внимание, что вы должны использовать двойные кавычки ( " ), чтобы окружить все строки; одинарные кавычки ( ' ) недопустимы. Да, это так, даже если JavaScript позволяет заключать строки в кавычки любого типа. Если вы хотите используйте двойные кавычки внутри строк JSON, используйте \" вместо этого.


Массив — это набор элементов, каждый из которых назначен определенному целому числу. Объект — это набор элементов, каждый из которых назначен определенной строке . Элементы называются значениями , а строки, используемые для их идентификации, называются ключами . Некоторые языки программирования называют такую ​​структуру данных хэш-таблицей или хэш-картой .

Мы могли бы представлять возраст людей в объекте так:

1
{ «Alan»: 44, «John»: 58, «Brian»: 19, «Eliza»: 4, «Jessie»: 58 }

В фигурных скобках написано «это объект», и, как и в случае с массивами, запятые разделяют разные элементы. Однако элементы даются парами , на этот раз. Проще увидеть, если мы добавим несколько новых строк и отступов:

1
2
3
4
5
6
7
{
    «Alan»: 44,
    «John»: 58,
    «Brian»: 19,
    «Eliza»: 4,
    «Jessie»: 58
}

В каждой паре двоеточие отделяет ключ (который является строкой) от значения (которое, в данном случае, является числом). Когда мы создавали массив, нам не нужно было указывать, какому целому числу был присвоен каждый элемент (т. Е. Нам нужно было указывать только значения, а не ключи), потому что они были назначены на основе порядка, в котором они были записаны в массив.

Вместо того, чтобы запрашивать второй или пятый элемент, как при обращении к массиву, с объектом вы будете запрашивать элемент «Alan» или «Eliza».

Чтобы сделать вещи более запутанными, объекты также позволяют использовать строки в качестве значений, а не только ключи. Таким образом, вы можете иметь такой объект:

01
02
03
04
05
06
07
08
09
10
11
12
{
    «Activetuts+»: «http://active.tutsplus.com/»,
    «Psdtuts+»: «http://psd.tutsplus.com/»,
    «Nettuts+»: «http://net.tutsplus.com/»,
    «Aetuts+»: «http://ae.tutsplus.com/»,
    «Vectortuts+»: «http://vector.tutsplus.com/»,
    «Audiotuts+»: «http://audio.tutsplus.com/»,
    «Cgtuts+»: «http://cg.tutsplus.com/»,
    «Phototuts+»: «http://photo.tutsplus.com/»,
    «Webdesigntuts+»: «http://webdesign.tutsplus.com/»,
    «Mobiletuts+»: «http://mobile.tutsplus.com/»
}

Таким образом, чтобы получить URL для данного сайта Tuts +, вы можете запросить его, используя имя сайта в качестве ключа. Однако обратное неверно — вы не можете использовать «http://cg.tutsplus.com/» для получения «Cgtuts +».

Те же правила о различных типах кавычек применяются к объектам как к массивам. Объекты также могут использовать строки, числа, true , false и null качестве значений (но только строки в качестве ключей).


Объекты и массивы также могут хранить другие объекты и массивы. Это позволяет нам создавать вложенные структуры данных; например:

01
02
03
04
05
06
07
08
09
10
11
12
{
    «Activetuts+»: { «url»: «http://active.tutsplus.com/», «hasPremium»: true },
    «Psdtuts+»: { «url»: «http://psd.tutsplus.com/», «hasPremium»: true },
    «Nettuts+»: { «url»: «http://net.tutsplus.com/», «hasPremium»: true },
    «Aetuts+»: { «url»: «http://ae.tutsplus.com/», «hasPremium»: true },
    «Vectortuts+»: { «url»: «http://vector.tutsplus.com/», «hasPremium»: true },
    «Audiotuts+»: { «url»: «http://audio.tutsplus.com/», «hasPremium»: true },
    «Cgtuts+»: { «url»: «http://cg.tutsplus.com/», «hasPremium»: true },
    «Phototuts+»: { «url»: «http://photo.tutsplus.com/», «hasPremium»: true },
    «Webdesigntuts+»: { «url»: «http://webdesign.tutsplus.com/», «hasPremium»: false },
    «Mobiletuts+»: { «url»: «http://mobile.tutsplus.com/», «hasPremium»: false }
}

Давайте посмотрим, что с немного больше пробелов:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
{
    «Activetuts+»:
    {
        «url»: «http://active.tutsplus.com/»,
        «hasPremium»: true
    },
    «Psdtuts+»:
    {
        «url»: «http://psd.tutsplus.com/»,
        «hasPremium»: true
    },
    «Nettuts+»:
    {
        «url»: «http://net.tutsplus.com/»,
        «hasPremium»: true
    },
    «Aetuts+»:
    {
        «url»: «http://ae.tutsplus.com/»,
        «hasPremium»: true
    },
    «Vectortuts+»:
    {
        «url»: «http://vector.tutsplus.com/»,
        «hasPremium»: true
    },
    «Audiotuts+»:
    {
        «url»: «http://audio.tutsplus.com/»,
        «hasPremium»: true
    },
    «Cgtuts+»:
    {
        «url»: «http://cg.tutsplus.com/»,
        «hasPremium»: true
    },
    «Phototuts+»:
    {
        «url»: «http://photo.tutsplus.com/»,
        «hasPremium»: true
    },
    «Webdesigntuts+»:
    {
        «url»: «http://webdesign.tutsplus.com/»,
        «hasPremium»: false
    },
    «Mobiletuts+»:
    {
        «url»: «http://mobile.tutsplus.com/»,
        «hasPremium»: false
    }
}

Каждый объект содержит два поля: одно с ключом "url" , значением которого является строка, содержащая URL-адрес сайта, и одно с ключом hasPremium , значением которого является логическое значение, которое истинно, если на сайте есть раздел Premium.

Мы не ограничены тем, чтобы иметь одинаковую структуру для каждого объекта в JSON. Например, мы могли бы добавить дополнительный URL, который указывает на URL программы Premium, но только для тех сайтов, у которых есть один:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
{
    «Activetuts+»:
    {
        «url»: «http://active.tutsplus.com/»,
        «hasPremium»: true,
        «premiumUrl»: «http://tutsplus.com/Premium-program/active-Premium/»
    },
    «Psdtuts+»:
    {
        «url»: «http://psd.tutsplus.com/»,
        «hasPremium»: true,
        «premiumUrl»: «http://tutsplus.com/Premium-program/psd-Premium/»
    },
    «Nettuts+»:
    {
        «url»: «http://net.tutsplus.com/»,
        «hasPremium»: true,
        «premiumUrl»: «http://tutsplus.com/Premium-program/net-Premium/»
    },
    «Aetuts+»:
    {
        «url»: «http://ae.tutsplus.com/»,
        «hasPremium»: true,
        «premiumUrl»: «http://tutsplus.com/Premium-program/ae-Premium/»
    },
    «Vectortuts+»:
    {
        «url»: «http://vector.tutsplus.com/»,
        «hasPremium»: true,
        «premiumUrl»: «http://tutsplus.com/Premium-program/vector-Premium/»
    },
    «Audiotuts+»:
    {
        «url»: «http://audio.tutsplus.com/»,
        «hasPremium»: true,
        «premiumUrl»: «http://tutsplus.com/Premium-program/audio-Premium/»
    },
    «Cgtuts+»:
    {
        «url»: «http://cg.tutsplus.com/»,
        «hasPremium»: true,
        «premiumUrl»: «http://tutsplus.com/Premium-program/cg-Premium/»
    },
    «Phototuts+»:
    {
        «url»: «http://photo.tutsplus.com/»,
        «hasPremium»: true,
        «premiumUrl»: «http://tutsplus.com/Premium-program/photo-Premium/»
    },
    «Webdesigntuts+»:
    {
        «url»: «http://webdesign.tutsplus.com/»,
        «hasPremium»: false
    },
    «Mobiletuts+»:
    {
        «url»: «http://mobile.tutsplus.com/»,
        «hasPremium»: false
    }
}

Мы могли бы даже включить массив всех последних учебников Премиум для данного сайта (я просто покажу Activetuts + здесь и ограничу его несколькими Премиумами, чтобы сэкономить место):

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
    «Activetuts+»:
    {
        «url»: «http://active.tutsplus.com/»,
        «hasPremium»: true,
        «premiumUrl»: «http://tutsplus.com/Premium-program/active-Premium/»
        «previousPremiums»:
        [
            «http://tutsplus.com/join/»,
            «http://active.tutsplus.com/tutorials/games/create-a-space-shooter-game-in-flash-using-as3http://tutsplus.com/join/»,
            «http://active.tutsplus.com/tutorials/games/obscuring-and-revealing-scenes-with-as3http://tutsplus.com/join/»,
            «http://active.tutsplus.com/tutorials/games/building-a-dynamic-shadow-casting-engine-in-as3http://tutsplus.com/join/»,
            «http://tutsplus.com/join/»
        ]
    },
     
    /** SNIP!
     
    «Mobiletuts+»:
    {
        «url»: «http://mobile.tutsplus.com/»,
        «hasPremium»: false
    }
}

Массив имеет смысл для перечисления Премиум, потому что я работаю в предположении, что любое приложение, которое фактически читает эти данные, просто отображает список учебников Премиум, а не нуждается в доступе к ним в соответствии с их названием — поэтому мы не нужно назначать им каждый строковый ключ.

Мы могли бы пойти еще дальше:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
{
    «Activetuts+»:
    {
        «url»: «http://active.tutsplus.com/»,
        «premium»:
        {
            «hasPremium»: true,
            «premiumUrl»: «http://tutsplus.com/Premium-program/active-Premium/»,
            «previousPremiums»:
            [
                {
                    «title»: «Create a Customizable Flash Quiz Application»,
                    «url»: «http://tutsplus.com/join/»,
                },
                {
                    «title»: «Create a Space Shooter Game in Flash Using AS3»,
                    «url»: «http://active.tutsplus.com/tutorials/games/create-a-space-shooter-game-in-flash-using-as3http://tutsplus.com/join/»,
                },
                {
                    «title»: «Obscuring and Revealing Scenes with AS3»,
                    «url»: «http://active.tutsplus.com/tutorials/games/obscuring-and-revealing-scenes-with-as3http://tutsplus.com/join/»,
                },
                {
                    «title»: «Building a Dynamic Shadow Casting Engine in AS3»,
                    «url»: «http://active.tutsplus.com/tutorials/games/building-a-dynamic-shadow-casting-engine-in-as3http://tutsplus.com/join/»,
                },
                {
                    «title»: «Animating the Envato Community Podcast»,
                    «url»: «http://tutsplus.com/join/»
                }
            ]
    },
     
    /** SNIP!
     
    «Mobiletuts+»:
    {
        «url»: «http://mobile.tutsplus.com/»,
        «premium»:
        {
            «hasPremium»: false
        }
    }
}

Уф! Если бы мы хотели, мы могли бы создавать объекты, которые содержат имена и URL-адреса профилей каждого автора каждого учебника Premium. Можете ли вы найти лучший способ сделать это?

Хранение массивов внутри массивов также может быть полезным; особенно для игр. Это может быть текущий макет платы Tic-Tac-Toe:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
[
    [
        1,
        2,
        0
    ],
    [
        0,
        1,
        0
    ]
    [
        0,
        2,
        1
    ]
]

Не видя этого? Попробуйте удалить некоторые пробелы:

1
2
3
4
5
[
    [1,2,0],
    [0,1,0],
    [0,2,1]
]

1 — ноль, 2 — крест, 0 — пустое место. Noughts выиграть! И я уверен, что вы можете увидеть, как нечто подобное можно использовать для линкоров, Connect 4 или Minesweeper. Для получения дополнительной информации о вложенных массивах, посмотрите мой предыдущий учебник .


Поскольку JSON очень популярен, для большинства языков программирования доступны синтаксические анализаторы (инструменты и библиотеки, которые декодируют один язык программирования, чтобы его мог понять другой), и генераторы (инструменты и библиотеки, которые делают противоположное; кодируют один язык программирования в другой). Просто поищите [JSON-парсер (название вашего языка}] . Я выделю некоторые из них, которые имеют отношение к Activetuts + читателям.


Стандартная библиотека для кодирования и декодирования данных JSON в AS3 — as3corelib ; см. мое руководство по использованию внешних библиотек, если вы не знаете, как его установить.

Вы можете декодировать строку в формате JSON в объекты и массивы AS3, передав ее в com.adobe.serialization.json.JSON.decode() ; возвращаемое значение будет либо массивом, либо объектом, в зависимости от JSON. Если вы передадите false в качестве второго аргумента, декодер не будет так строго следовать стандарту JSON, так что вы можете обойтись без форматирования с задержками.

Вы можете закодировать объект или массив AS3 (который может содержать вложенные объекты и массивы) в строку JSON, передав ее в com.adobe.serialization.json.JSON.encode() ; возвращаемое значение будет String.

Было объявлено, что будущие версии Flash будут включать собственный синтаксический анализ JSON, поэтому вскоре для этого не нужно использовать as3corelib.


Чтобы разобрать JSON, просто добавьте ссылку на System.Json . Потом:

1
2
3
#using System.Json;
 
decoded = JsonValue.Parse(jsonString);

Кодировать объект в строку JSON немного сложнее. Сначала вы должны создать контракт данных для типа объекта, который вы хотите кодировать; давайте назовем нашу Thing , а фактический объект myThing . Потом:

01
02
03
04
05
06
07
08
09
10
#using System.Runtime.Serialization.Json;
 
MemoryStream myStream = new MemoryStream();
DataContractJsonSerializer jsonEncoder = new DataContractJsonSerializer(typeof(Thing));
jsonEncoder.WriteObject(myStream, myThing);
 
myStream.Position = 0;
StreamReader sr = new StreamReader(myStream);
 
encoded = sr.ReadToEnd();

Вы также можете использовать этот метод для декодирования строки JSON в определенный класс объекта:

1
2
3
4
#using System.Runtime.Serialization.Json;
 
myStream.Position = 0;
myOtherThing = ser.ReadObject(myStream);

Для получения дополнительной информации см. Страницы MSDN Работа с данными JSON и Практическое руководство. Сериализация и десериализация данных JSON .


Вы можете просто передать строку JSON в eval() в JavaScript, но это страшная угроза безопасности. Большинство современных браузеров поддерживают функцию JSON.parse() , которая будет анализировать строку JSON в объекты JavaScript, и JSON.stringify() , которая превратит объект или массив JavaScript в строку JSON.

Дуглас Крокфорд создал библиотеку для этого в старых браузерах; это доступно на github .


Существует сборка C # под названием LitJSON, которую вы можете использовать в своих проектах Unity для анализа и генерации JSON. Вы можете использовать это, даже если ваш проект написан на JavaScript или Boo, а не на C #.

Чтобы декодировать объект Unity в строку JSON:

1
2
3
#using LitJson;
 
string jsonString = JsonMapper.ToJson (myObject);

Чтобы кодировать строку JSON в объект Unity типа Thing:

1
2
3
#using LitJson;
 
Thing myThing = JsonMapper.ToObject<Thing> (jsonString);

Руководство по LitJSON великолепно; Я рекомендую прочитать это для большего руководства.


JSON.org имеет длинный список библиотек для различных платформ и языков — плюс, вы можете искать в Google, как упоминалось выше;)

На этом сайте также есть отличная визуализация того, как может быть построен JSON, и множество деталей, выходящих за рамки того, что я объяснил в этом кратком введении. Проверьте это, если хотите узнать больше!