Skip to content

Instantly share code, notes, and snippets.

@syohex
Created May 25, 2016 10:55
Show Gist options
  • Save syohex/09b4c284937f2314975dc50b2661d1f7 to your computer and use it in GitHub Desktop.
Save syohex/09b4c284937f2314975dc50b2661d1f7 to your computer and use it in GitHub Desktop.
Convert JSON to go struct definition
#!perl
use strict;
use warnings;
use JSON::PP ();
use Getopt::Long ();
use Scalar::Util ();
my $struct_name = "";
Getopt::Long::GetOptions(
"name|n=s" => \$struct_name,
) or die "Usage: json2gostruct.pl -n struct_name";
main($struct_name);
sub main {
my $name = shift;
my $input = do {
local $/;
<STDIN>;
};
my $json = JSON::PP::decode_json($input);
unless (ref $json eq 'HASH') {
die "Support only object type!!";
}
my $gostruct = encode($json, $name, 0);
print $gostruct;
}
sub indent {
my $nest = shift;
return "\t" x $nest;
}
sub encode {
my ($object, $name, $nest) = @_;
my @lines;
if ($nest == 0) {
push @lines, "type $name struct {";
} else {
push @lines, "struct {";
}
push @lines, encode_element($object, $name, $nest+1);
if ($nest == 0) {
push @lines, "}\n";
} else {
my $indent = indent($nest);
push @lines, "${indent}}";
}
return join "\n", @lines;
}
sub encode_element {
my ($object, $name, $nest) = @_;
my $indent = indent($nest);
my @ret;
for my $key (sort keys %{$object}) {
my $val = $object->{$key};
my $type;
if (ref $val eq 'HASH') {
$type = encode($val, $name, $nest);
} elsif (ref $val eq 'ARRAY') {
$type = "[]" . guess_array_type($val, $name, $nest);
} elsif (Scalar::Util::looks_like_number($val)) {
if (is_float($val)) {
$type = "float64";
} else {
$type = "int";
}
} else {
$type = "string";
}
my $field_decl = sprintf "%s%s %s `json:%s`", $indent, ucfirst($key), $type, $key;
push @ret, $field_decl;
}
return @ret;
}
sub guess_array_type {
my ($arr, $name, $nest) = @_;
return "string" if scalar @{$arr} == 0;
my $first_type = ref $arr->[0];
unless ($first_type) {
my $is_num = Scalar::Util::looks_like_number($arr->[0]);
if ($is_num) {
my $num = grep { Scalar::Util::looks_like_number($_) } @{$arr};
if ($num == scalar @{$arr}) {
if (is_float($arr->[0])) {
return "float64";
} else {
return "int";
}
}
}
return "string";
}
if ($first_type eq "ARRAY") {
return guess_array_type($arr->[0], $name, $nest);
} elsif ($first_type eq "HASH") {
return encode($arr->[0], $name, $nest);
}
return "string";
}
sub is_float {
my $num = shift;
$num =~ m{\.};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment