Как стать автором
Обновить

Комментарии 40

Я так понимаю, читать файл обратно, задачи не стоит.
В будущем понадобится. Собственная реализация есть, но наверное посмотрю готовое.
Есть ещё одна open source библиотека для работы с json (JsonBox), очень удобная в использовании, осваивается минут за 5.
Спасибо, посмотрю.
А если в строке будет кавычка? Не нашел в коде экранирование.
В 2do этот пункт есть, но пока не реализован.
Это понятно, что лисапед. Надеюсь, что оригинальный. Такого наглого использования цикла for я нигде сам не встречал :).
Согласен. Да и main для неокрепших умов выглядит так, что хочется руки поотрывать посмотреть как и зачем такое сделано.
На фоне этой красоты
//Внутри массива ключ игнорируется, даже если ошибочно задан

смотрится не очень.
Рубанул комментарии. А за что руки оторвать, можно подробнее? Ну за (char *)&i, оно понятно, а еще?
Дело не в комментарии, а в том, что параметр не нужен.
Ну, за оригинальную запись. Вам-то оно понятно, а любой непосвященный сразу думает «WTF?» И только потом, если разберется «О, как красиво!» ;)
Эх, если бы я умел делать #define FOO(...) с переменным числом аргументов, то можно было бы еще красивее забацать. В JSONе можно использовать null в качестве значения, так и напрашивается сделать его через VALUE(«Key»), а вот фиг. Но я еще работаю над этой проблемой ;).
Еще очень напрягает, что нельзя нормально перегрузить функции TJsonTagCloser::Write***. Используются-то его наследники, не в каждом же перегружать. Тоже думаю, как сделать красиво.
image

Но велосипед не плохой получился :)
Согласен с предыдущими комментаторами. Есть вещи, самостоятельно писать которые следует только в исключительных случаях.
blog.newrelic.com/2014/07/08/7-things-never-code/
Я с этим согласен. Но я непрофессиональный программист, поэтому такие задачи для меня скорее тренировка и даже что-то вроде хобби. У меня редко получается хороший код, но тут, похоже, исключение. Если честно, то сам офигел от чистоты и естественности скрипта описания формата данных, насколько хорошо в него вписываются конструкции С++. Собственно поэтому и рискнул показать общественности.
Советую rapidjson. Из преимуществ — кроссплатформенный, быстрый, понимает различные кодировки, хорошо документирован и поддерживает или будет новые изменения в С++11. Велосипед, конечно, хорошо делать когда есть время или для учебы, но это не настолько интересно чтобы писать свой 101 парсер(писатель) Json/Xml формата.
Спасибо за наводку. Времени нет, но было интересно, наверное это все оправдывает.
json всем хорош, но вот с датами там не все гладко в отличии от xml
Очень интересно послушать что именно. Как по мне, текст и там, и там.
json не предлагает определенного формата представления даты/времени, из-за чего могут возникнуть проблемы при его использовании между php и .net например. http://stackoverflow.com/questions/10286204/the-right-json-date-format
Ну, если Вы про xml schema, где описан тип xs:dateTime, то он как раз ISO 8601 — пользуйтесь им же и в JSON и большинство библиотек его поймут, не так ли?
У xml существует такое понятие, как схема — которая подскажет, где текст — это просто текст, а где он вообще-то дата. Схема может быть строгой (значение такого-то атрибута — всегда дата) или нестрогой (дата в тексте выделяется тегом date), но она всегда есть. Более того, в xml парсинг даты ничем не отличается от, к примеру, парсинга числа.

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

Надо понимать, что это не является недостатком json. Просто если надо часто работать с датами — то json оказывается ничем не проще xml.
полностью с вами согласен
что значит числа не надо парсить? они передаются точно так же строкой в человекочитаемом виде, из этой строки все равно нужно парсить число
но она всегда есть
Это где она всегда есть? Сколько API сайтов не перелопатил, нигде не встречал. XML Schema существует так же, как и JSON Schema (документ IETF, между прочим). А вот то, что на практике его мало кто использует, это уже другой вопрос.
Чому бы не осилить boost::property_tree?
#include <iostream>
#include <unordered_map>
#include <boost/property_tree/json_parser.hpp>

int main()
{
    auto pt = boost::property_tree::ptree{};
    pt.put("Comment", "My comment");
    pt.put("Count", 10);
    pt.put("DiskParam.DB", 10.0);
    pt.put("DiskParam.DBAngle", 1.234);
    pt.put("Range", true);

    auto blades = std::unordered_map<std::string, int>{{"A", 1}, {"B", 2}, {"C", 2}};

    auto bladesTree = boost::property_tree::ptree{};
    for (const auto &kv : blades) {
        auto blade = boost::property_tree::ptree{};
        blade.add("Caption", kv.first);
        blade.add("Value", kv.second);
        bladesTree.push_back(std::make_pair("", blade));
    }

    pt.add_child("Blades", bladesTree);

    auto slotsTree = boost::property_tree::ptree{};
    for (auto i = 0; i < 3; i++) {
        auto slot = boost::property_tree::ptree{std::to_string(i)};
        slotsTree.push_back(std::make_pair("", slot));
    }

    pt.add_child("Slots", slotsTree);

    auto buf = std::ostringstream{};
    boost::property_tree::write_json(buf, pt);
    std::cout << buf.str();
}
Большое спасибо, что не поленились написать пример использования.
Я бы рекомендовал более легкую, сам использую cajun и после boost прям как бальзам на душу
Хмм…
Простой аналог на Haskell (inspired by realworldhaskell):

import Data.Char
import Data.List (intercalate)
        
data JValue = JString String
            | JNumber Double
            | JBool Bool
            | JNull
            | JObject [(String, JValue)]
            | JArray [JValue]
              deriving Show

renderJValue :: JValue -> String
renderJValue (JString s)   = show s
renderJValue (JNumber n)   = show n
renderJValue (JBool True)  = "true"
renderJValue (JBool False) = "false"
renderJValue JNull         = "null"
renderJValue (JObject o) = "{" ++ pairs o ++ "}"
    where pairs [] = ""
          pairs ps = intercalate ", " (map renderPair ps)
          renderPair (k, v) = show k ++ ": " ++ renderJValue v
renderJValue (JArray a) = "[" ++ values a ++ "]"
    where values [] = ""
          values vs = intercalate ", " (map renderJValue vs)
    
main = putStrLn $ renderJValue (JObject [
        ("Comment", JString "My comment"), 
        ("Count", JNumber 10),
        ("DiskParam", JObject [
            ("DB", JNumber 10), 
            ("DBAngle", JNumber 1.234)
        ]),
        ("Range", JBool True),
        ("Blades", JArray $ map (\ch -> 
            JObject [
                ("Caption", JString (ch:[])),
                ("Value", JNumber (fromIntegral (ord ch)))
            ])  ['A'..'C']),
        ("Slots", JArray [JNumber 0, JNumber 1, JNumber 2])
    ])


Кажется компактнее получилось :)
Ищущие компактности используют Javascript (JSON.stringify) или Python (json.dumps). Инициализация сериализуемых объектов в этих языках совпадает по синтаксису с JSON.

А все велосипедисты навернутся на первой неэкранированной кавычке, бэкслеше, на переносах строк, на юникоде и много ещё на чём.
Я знаю про эти сложности, но не старался затащить сюда полную реализацию. Наоборот, резал код как можно компактнее. Только необходимое для иллюстрации совершенно оригинального подхода к формированию XML-подобных документов.
Ого! В такой размер исходника я не помещусь, даже если максимально выжать из него всю воду. Но за первенство по размеру исполняемого файла вполне поборюсь, предполагаю влезть в 4Кб.
Забавный язык, спасибо за комментарий.
Вспомнился мой наивный XML-парсер… Да, все мы иногда пишем велосипеды ;)
Совет программисту на любом языке: погляди, нет ли в конце страницы http://json.org/ исходного кода для работы с JSON на твоём языке.

Если есть — то не пиши собственный код. (Если неймётся, то пиши — но не используй в деле до тех пор, пока он не станет во всём лучше имеющегося.)
Вы будете смеяться, но я пишу с использованием разработанной технологии еще один вЕлик. Библиотеку чтения JSON. Примерно так выглядит это самое чтение в программе:
  OBJECT("")
  {
    VALUE("Comment", Header.Comment);
    VALUE("Count",   Header.Count);
    OBJECT("DiskParam")
    {
      VALUE("DB",      Header.DB);
      VALUE("DBAngle", Header.DBAngle);
    }
    VALUE("Range",   Header.Range);

    //Чтение массива с неизвестным числом элементов
    ARRAY_WHILE("Blades", BladeCount)
    {
      TBlade Blade;
      OBJECT("")
      {
        VALUE("Caption", Blade.Caption);
        VALUE("Value",   Blade.BaseChar);
      }
      if(!ERROR)
      {
        NewBlades=realloc(Blades, BladeCount+1);
        if(NewBlades)
        {
          Blades=NewBlades;
          Blades[BladeCount]=Blade;
        }
      }
    }

    //Чтение массива с известным или ограниченным числом элементов
    ARRAY_FOR("Slots", SlotsCount, MAX_ELEMENTS)
      VALUE("", Slots[SlotsCount]);

    //Обработка ситуаций, когда значение может быть неподходящего типа
    double Temp;
    VALUE("NCount", Temp)
      Header.NCount=(int)(Temp+0.5);
  }
Я просто уверен, такого синтаксиса вы еще нигде не видели :). Имеет смысл писать статью или снова заминусуете велосипедиста?
Библиотеки хоть совместимы? Я думаю, в хабе «Ненормальное программирование» никто минусовать не будет.
Пока несовместимы. Спасибо за наводку!
Это же убого! Бросьте Вы это. Уверяю спустя некоторое время «Вы-в-будущем» очень не хорошо выскажется о «Вы-сейчас»!
А что убого-то? Я считаю, что у меня скрипт описания структуры файла данных неплохой. Легко читается, допускает всевозможные проверки, контроль ошибок и тд. Главное — мне нравится то, что я делаю. Это не тяжкий труд, это радость творчества.
Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.