1

I want to iterate over the JSON using CTFE. I have tried both std.json and vibe.data.json, but there is no luck. I am not sure what I am missing.

import std.stdio;
import std.json;
import std.array;
import vibe.data.json;

void main()
{
    enum string config = `{ "ModelNames": [ "Bank", "Biller", "Aggregator" ] }`;
    const auto c1 = parseJSON(config);
    immutable auto c2 = parseJsonString(config);
    
    foreach (key; c1["ModelNames"].array)
        writeln(key.get!string);

    foreach (key; c2["ModelNames"])
        writeln(key.get!string);

    // static foreach (key; c1["ModelNames"].array)
    //  pragma(msg, key.get!string);

    // static foreach (key; c2["ModelNames"])
    //  pragma(msg, key.get!string);
}
  • to be available at compile time your variables need to be `enum` or `static immutable`, however the libraries (std.json and vibe.data.json) don't seem to support this use-case. You may be able to use a lighter JSON parser or parse manually. Pegged actually has a JSON parser example and works at compile time, but you have to interpret the data yourself. – WebFreak001 Apr 10 '21 at 15:10
  • I don't know why you're saying that `std.json` doesn't support this, because it just works. – Vladimir Panteleev Apr 10 '21 at 15:26
  • Can you please show me what I am doing wrong, as when I removed the comments the program does not compile? – m.tariqsiddiqui Apr 10 '21 at 15:29

2 Answers2

5

Wrap your logic into a regular D function, then get the compiler to evaluate it at compile-time by calling it is a context where the result must be known at compile-time, such as using the result in an enum:

import std.algorithm.iteration;
import std.stdio;
import std.json;
import std.array;

void main()
{
    enum string config = `{ "ModelNames": [ "Bank", "Biller", "Aggregator" ] }`;

    static string[] getModelNames(string json)
    {
        auto c1 = parseJSON(json);
        return c1["ModelNames"].array.map!(item => item.str).array;
    }

    enum string[] modelNames = getModelNames(config);
    pragma(msg, modelNames);
}
Vladimir Panteleev
  • 24,651
  • 6
  • 70
  • 114
  • Thanks Vladimir, it is working. I have also upvoted your answer but it showing me a message. Thanks for the feedback! Votes cast by those with less than 15 reputation are recorded, but do not change the publicly displayed post score. – m.tariqsiddiqui Apr 10 '21 at 15:33
0

Thanks to Vladimir, the trick he specifies work perfectly both for std.json and vibe.data.json.

import std.algorithm.iteration;
import std.stdio;
import std.json;
import std.array;
import vibe.data.json;

void main()
{
    enum string config = `{ "ModelNames": [ "Bank", "Biller", "Aggregator" ] }`;
    immutable auto c1 = parseJSON(config);
    immutable auto c2 = parseJsonString(config);
    
    static foreach (key; c1["ModelNames"].array.map!(item => item).array)
        pragma(msg, key.get!string);

    static foreach (key; c2["ModelNames"].array.map!(item => item).array)
        pragma(msg, key.get!string);
}