• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

orangeduck/json2c: Convert JSON to C data literals

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称:

orangeduck/json2c

开源软件地址:

https://github.com/orangeduck/json2c

开源编程语言:

C 63.6%

开源软件介绍:

json2c

Convert JSON to C data literals.

For example this...

{
     "firstName": "John",
     "lastName": "Smith",
     "age": 25,
     "address":
     {
         "streetAddress": "21 2nd Street",
         "city": "New York",
         "state": "NY",
         "postalCode": "10021"
     },
     "phoneNumber":
     [
         {
           "type": "home",
           "number": "212 555-1234"
         },
         {
           "type": "fax",
           "number": "646 555-4567"
         }
     ]
}

becomes this...

typedef struct {
    const char* streetAddress;
    const char* city;
    const char* state;
    const char* postalCode;
} customerAddress;

typedef struct {
    const char* type;
    const char* number;
} customerPhoneNumberEntry;

enum { CUSTOMERPHONENUMBERCOUNT = 2 };

typedef customerPhoneNumberEntry customerPhoneNumber[CUSTOMERPHONENUMBERCOUNT];

typedef struct {
    const char* firstName;
    const char* lastName;
    long age;
    customerAddress address;
    customerPhoneNumber phoneNumber;
} customer;

extern customer customerObject;

and this...

customer customerObject = {
    .firstName = "John", 
    .lastName = "Smith", 
    .age = 25, 
    .address = {
        .streetAddress = "21 2nd Street", 
        .city = "New York", 
        .state = "NY", 
        .postalCode = "10021"
    }, 
    .phoneNumber = {
        {
            .type = "home", 
            .number = "212 555-1234"
        }, 
        {
            .type = "fax", 
            .number = "646 555-4567"
        }
    }
};

Usage

Simply run json2c on some JSON file to create a matching header and source file in the same directory.

pip install json2c
json2c -c customer.json

The -c flag is used for CamelCase friendly configuration. Run with --help to see the full list of options. This includes lots of fine grained options for changing the style and conventions of the generated C code to match your project.

Motivation

Generating data literals in C is useful for embedding configuration, mark up, or even whole databases into C programs.

It has several advantages over loading the data at runtime - it doesn't require a parser, gives lightning fast access, and uses minimal memory. This is because the whole thing is stripped of meta-data such as field names, there is no hashing required, and all access patterns are resolved at compile-time. The final bonus is that objects can be accessed with familiar dot notation right from C!

Conversion from JSON is a natural choice because of how easy it is to write by hand, and the abundance of tools that can generate and edit it.

An example application for this tool might be in the construction of an RPG. Given a large amount of data to enter, such as weapon and item details, the data entry could be generated (or written by hand), and then this tool could be used to embed it directly at compile time.

The downside is of course that embedding too much data can overly increase the size of the executable, which could result in your program being sluggish to start.

About

The basic process of json2c is simple.

JSON is recursively converted to equivalent C. Literals such as strings, integers, and booleans, are converted directly to C types. Hashes are converted to C structs, and a type definition is generated to go with them.

Trouble only starts trying to convert JSON lists, as C does not support heterogeneous lists.

Luckily for us, while JSON technically has heterogeneous lists, most data you encounter in the wild tends to use lists somewhat homogeneously. Because of this if json2c encounters a list it attempts to unify all the types within the list into a single matching type. This it can write out as an array or a pointer.

To do this unification a number of heuristics are used. For example null can be unified with various other types using pointers and other tricks. Missing entries into hashes can be added, or two arrays of different fixed sizes can be converted into variable length arrays. Basic types can be promoted to match, such as converting int to float or bool to int.

While some of the heuristics don't always make sense, this approach has overall proven very effective for almost all example JSON data I've found. This means json2c is almost always capable of producing something meaningful.

Various options about how types and names are generated can be set on the command line. This allows you to generate C code that matches your project, and looks hand-written.

Examples

$ json2c -c interop.json
{
    "ResultSet": {
        "totalResultsAvailable": "1827221",
        "totalResultsReturned": 2,
        "firstResultPosition": 1,
        "Result": [
            {
                "Title": "potato jpg",
                "Summary": "Kentang Si bungsu dari keluarga Solanum tuberosum L ini ternyata memiliki khasiat untuk mengurangi kerutan  jerawat  bintik hitam dan kemerahan pada kulit  Gunakan seminggu sekali sebagai",
                "Url": "http://www.mediaindonesia.com/spaw/uploads/images/potato.jpg",
                "ClickUrl": "http://www.mediaindonesia.com/spaw/uploads/images/potato.jpg",
                "RefererUrl": "http://www.mediaindonesia.com/mediaperempuan/index.php?ar_id=Nzkw",
                "FileSize": 22630,
                "FileFormat": "jpeg",
                "Height": "362",
                "Width": "532",
                "Thumbnail": {
                    "Url": "http://thm-a01.yimg.com/nimage/557094559c18f16a",
                    "Height": "98",
                    "Width": "145"
                }
            },
            {
                "Title": "potato jpg",
                "Summary": "Introduction of puneri aloo This is a traditional potato preparation flavoured with curry leaves and peanuts and can be eaten on fasting day  Preparation time   10 min",
                "Url": "http://www.infovisual.info/01/photo/potato.jpg",
                "ClickUrl": "http://www.infovisual.info/01/photo/potato.jpg",
                "RefererUrl": "http://sundayfood.com/puneri-aloo-indian-%20recipe",
                "FileSize": 119398,
                "FileFormat": "jpeg",
                "Height": "685",
                "Width": "1024",
                "Thumbnail": {
                    "Url": "http://thm-a01.yimg.com/nimage/7fa23212efe84b64",
                    "Height": "107",
                    "Width": "160"
                }
            }
        ]
    }
}
#ifndef INTEROP_H
#define INTEROP_H

#include <stdlib.h>
#include <stdbool.h>
#include <math.h>

typedef struct {
    const char* Url;
    const char* Height;
    const char* Width;
} interopResultSetResultEntryThumbnail;

typedef struct {
    const char* Title;
    const char* Summary;
    const char* Url;
    const char* ClickUrl;
    const char* RefererUrl;
    long FileSize;
    const char* FileFormat;
    const char* Height;
    const char* Width;
    interopResultSetResultEntryThumbnail Thumbnail;
} interopResultSetResultEntry;

enum { INTEROPRESULTSETRESULTCOUNT = 2 };

typedef interopResultSetResultEntry interopResultSetResult[INTEROPRESULTSETRESULTCOUNT];

typedef struct {
    const char* totalResultsAvailable;
    long totalResultsReturned;
    long firstResultPosition;
    interopResultSetResult Result;
} interopResultSet;

typedef struct {
    interopResultSet ResultSet;
} interop;

extern interop interopObject;

#endif
#include "interop.h"

interop interopObject = {
    .ResultSet = {
        .totalResultsAvailable = "1827221", 
        .totalResultsReturned = 2, 
        .firstResultPosition = 1, 
        .Result = {
            {
                .Title = "potato jpg", 
                .Summary = "Kentang Si bungsu dari keluarga Solanum tuberosum L ini ternyata memiliki khasiat untuk mengurangi kerutan  jerawat  bintik hitam dan kemerahan pada kulit  Gunakan seminggu sekali sebagai", 
                .Url = "http://www.mediaindonesia.com/spaw/uploads/images/potato.jpg", 
                .ClickUrl = "http://www.mediaindonesia.com/spaw/uploads/images/potato.jpg", 
                .RefererUrl = "http://www.mediaindonesia.com/mediaperempuan/index.php?ar_id=Nzkw", 
                .FileSize = 22630, 
                .FileFormat = "jpeg", 
                .Height = "362", 
                .Width = "532", 
                .Thumbnail = {
                    .Url = "http://thm-a01.yimg.com/nimage/557094559c18f16a", 
                    .Height = "98", 
                    .Width = "145"
                }
            }, 
            {
                .Title = "potato jpg", 
                .Summary = "Introduction of puneri aloo This is a traditional potato preparation flavoured with curry leaves and peanuts and can be eaten on fasting day  Preparation time   10 min", 
                .Url = "http://www.infovisual.info/01/photo/potato.jpg", 
                .ClickUrl = "http://www.infovisual.info/01/photo/potato.jpg", 
                .RefererUrl = "http://sundayfood.com/puneri-aloo-indian-%20recipe", 
                .FileSize = 119398, 
                .FileFormat = "jpeg", 
                .Height = "685", 
                .Width = "1024", 
                .Thumbnail = {
                    .Url = "http://thm-a01.yimg.com/nimage/7fa23212efe84b64", 
                    .Height = "107", 
                    .Width = "160"
                }
            }
        }
    }
};
json2c viewer.json --no-array-count-uppercase --no-guard-uppercase
{"menu": {
    "header": "SVG Viewer",
    "items": [
        {"id": "Open"},
        {"id": "OpenNew", "label": "Open New"},
        null,
        {"id": "ZoomIn", "label": "Zoom In"},
        {"id": "ZoomOut", "label": "Zoom Out"},
        {"id": "OriginalView", "label": "Original View"},
        null,
        {"id": "Quality"},
        {"id": "Pause"},
        {"id": "Mute"},
        null,
        {"id": "Find", "label": "Find..."},
        {"id": "FindAgain", "label": "Find Again"},
        {"id": "Copy"},
        {"id": "CopyAgain", "label": "Copy Again"},
        {"id": "CopySVG", "label": "Copy SVG"},
        {"id": "ViewSVG", "label": "View SVG"},
        {"id": "ViewSource", "label": "View Source"},
        {"id": "SaveAs", "label": "Save As"},
        null,
        {"id": "Help"},
        {"id": "About", "label": "About Adobe CVG Viewer..."}
    ]
}}
#ifndef viewer_h
#define viewer_h

#include <stdlib.h>
#include <stdbool.h>
#include <math.h>

typedef struct {
    const char* label;
    const char* id;
} viewer_menu_items_entry;

enum { viewer_menu_items_count = 22 };

typedef viewer_menu_items_entry* viewer_menu_items[viewer_menu_items_count];

typedef struct {
    const char* header;
    viewer_menu_items items;
} viewer_menu;

typedef struct {
    viewer_menu menu;
} viewer;

extern viewer viewer_object;

#endif
#include "viewer.h"

viewer viewer_object = {
    .menu = {
        .header = "SVG Viewer", 
        .items = {
            (viewer_menu_items_entry[]){
                {
                    .label = NULL, 
                    .id = "Open"
                }
            }, 
            (viewer_menu_items_entry[]){
                {
                    .label = "Open New", 
                    .id = "OpenNew"
                }
            }, 
            NULL, 
            (viewer_menu_items_entry[]){
                {
                    .label = "Zoom In", 
                    .id = "ZoomIn"
                }
            }, 
            (viewer_menu_items_entry[]){
                {
                    .label = "Zoom Out", 
                    .id = "ZoomOut"
                }
            }, 
            (viewer_menu_items_entry[]){
                {
                    .label = "Original View", 
                    .id = "OriginalView"
                }
            }, 
            NULL, 
            (viewer_menu_items_entry[]){
                {
                    .label = NULL, 
                    .id = "Quality"
                }
            }, 
            (viewer_menu_items_entry[]){
                {
                    .label = NULL, 
                    .id = "Pause"
                }
            }, 
            (viewer_menu_items_entry[]){
                {
                    .label = NULL, 
                    .id = "Mute"
                }
            }, 
            NULL, 
            (viewer_menu_items_entry[]){
                {
                    .label = "Find...", 
                    .id = "Find"
                }
            }, 
            (viewer_menu_items_entry[]){
                {
                    .label = "Find Again", 
                    .id = "FindAgain"
                }
            }, 
            (viewer_menu_items_entry[]){
                {
                    .label = NULL, 
                    .id = "Copy"
                }
            }, 
            (viewer_menu_items_entry[]){
                {
                    .label = "Copy Again", 
                    .id = "CopyAgain"
                }
            }, 
            (viewer_menu_items_entry[]){
                {
                    .label = "Copy SVG", 
                    .id = "CopySVG"
                }
            }, 
            (viewer_menu_items_entry[]){
                {
                    .label = "View SVG", 
                    .id = "ViewSVG"
                }
            }, 
            (viewer_menu_items_entry[]){
                {
                    .label = "View Source", 
                    .id = "ViewSource"
                }
            }, 
            (viewer_menu_items_entry[]){
                {
                    .label = "Save As", 
                    .id = "SaveAs"
                }
            }, 
            NULL, 
            (viewer_menu_items_entry[]){
                {
                    .label = NULL, 
                    .id = "Help"
                }
            }, 
            (viewer_menu_items_entry[]){
                {
                    .label = "About Adobe CVG Viewer...", 
                    .id = "About"
                }
            }
        }
    }
};
json2c -c youtube.json
{"apiVersion":"2.0",
 "data":{
    "updated":"2010-01-07T19:58:42.949Z",
    "totalItems":800,
    "startIndex":1,
    "itemsPerPage":1,
    "items":[
        {"id":"hYB0mn5zh2c",
         "uploaded":"2007-06-05T22:07:03.000Z",
         "updated":"2010-01-07T13:26:50.000Z",
         "uploader":"GoogleDeveloperDay",
         "category":"News",
         "title":"Google Developers Day US - Maps API Introduction",
         "description":"Google Maps API Introduction ...",
         "tags":[
            "GDD07","GDD07US","Maps"
         ],
         "thumbnail":{
            "default":"http://i.ytimg.com/vi/hYB0mn5zh2c/default.jpg",
            "hqDefault":"http://i.ytimg.com/vi/hYB0mn5zh2c/hqdefault.jpg"
         },
         "player":{
            "default":"http://www.youtube.com/watch?vu003dhYB0mn5zh2c"
         },
         "content":{
            "1":"rtsp://v5.cache3.c.youtube.com/CiILENy.../0/0/0/video.3gp",
            "5":"http://www.youtube.com/v/hYB0mn5zh2c?f...",
            "6":"rtsp://v1.cache1.c.youtube.com/CiILENy.../0/0/0/video.3gp"
         },
         "duration":2840,
         "aspectRatio":"widescreen",
         "rating":4.63,
         "ratingCount":68,
         "viewCount":220101,
         "favoriteCount":201,
         "commentCount":22,
         "status":{
            "value":"restricted",
            "reason":"limitedSyndication"
         },
         "accessControl":{
            "syndicate":"allowed",
            "commentVote":"allowed",
            "rate":"allowed",
            "list":"allowed",
            "comment":"allowed",
            "embed":"allowed",
            "videoRespond":"moderated"
         }
        }
    ]
 }
}
#ifndef YOUTUBE_H
#define YOUTUBE_H

#include <stdlib.h>
#include <stdbool.h>
#include <math.h>

enum { YOUTUBEDATAITEMSENTRYTAGSCOUNT = 3 };

typedef const char* youtubeDataItemsEntryTags[YOUTUBEDATAITEMSENTRYTAGSCOUNT];

typedef struct {
    const char* _default;
    const char* hqDefault;
} youtubeDataItemsEntryThumbnail;

typedef struct {
    const char* _default;
} youtubeDataItemsEntryPlayer;

typedef struct {
    const char* _1;
    const char* _5;
    const char* _6;
} youtubeDataItemsEntryContent;

typedef struct {
    const char* value;
    const char* reason;
} youtubeDataItemsEntryStatus;

typedef struct {
    const char* syndicate;
    const char* commentVote;
    const char* rate;
    const char* list;
    const char* comment;
    const char* embed;
    const char* videoRespond;
} youtubeDataItemsEntryAccessControl;

typedef struct {
    const char* id;
    const char* uploaded;
    const char* updated;
    const char* uploader;
    const char* category;
    const char* title;
    const char* description;
    youtubeDataItemsEntryTags tags;
    youtubeDataItemsEntryThumbnail thumbnail;
    youtubeDataItemsEntryPlayer player;
    youtubeDataItemsEntryContent content;
    long duration;
    const char* aspectRatio;
     
                       
                    
                    

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
OscarGodson/JSONP: Super Tiny JSONP Library发布时间:2022-07-09
下一篇:
Tonejs/Midi: Convert MIDI into Tone.js-friendly JSON发布时间:2022-07-09
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap