struct room_index_data
{
ROOM_INDEX_DATA * next;
CHAR_DATA * people;
OBJ_DATA * contents;
EXTRA_DESCR_DATA * extra_descr;
AREA_DATA * area;
EXIT_DATA * exit [6];
char * name;
char * description;
sh_int vnum;
sh_int room_flags;
sh_int light;
sh_int sector_type;
};
my $room_index_data = {
next => undef,
people => [],
contents => [],
extra_descr => [],
area => undef,
exit => [undef,undef,undef,undef,undef,undef],
name => '',
description => '',
vnum => undef,
room_flags => 0,
light => 0,
sector_type => undef,
};
my $people_data = {
name => "Bob Smith"
address => "123 Main St.",
city => "MyTown",
state => "MyState",
email => "bob@yahoo.com",
password => "password"
};
my $people_data = {
name => "Bob Smith"
address => "123 Main St.",
city => "MyTown",
state => "MyState",
email => "bob@yahoo.com",
password => "password"
};
my $people_data = {
name => "Bob Smith"
address => "123 Main St.",
city => "MyTown",
state => "MyState",
email => "bob@yahoo.com",
password => "password"
};
my $people_data = {
name => "Bob Smith"
address => "123 Main St.",
city => "MyTown",
state => "MyState",
email => "bob@yahoo.com",
password => "password"
};
#!/usr/bin/perl -w
package Example::Person;
use strict;
use warnings;
use English -no_match_vars;
use JSON;
sub load_file {
my $filename = shift;
return undef if !defined $filename or !-r $filename;
my $data = '';
open FP, "<$filename" or die "Cannot open $filename: $!";
while(<FP>) {
$data .= $_;
}
close FP;
return $data;
}
sub new {
my $class = shift;
my $person = shift;
my $self = {};
if( defined $person ) {
my $filename = "/lib/people/storage/$person.json";
if ( -r $filename ) {
my $data = load_file $filename;
$self = decode_json $data;
} else {
$self->{filename} = $filename;
}
} else {
$self = {
filename => "/lib/people/storage/bsmith.json",
name => "Bob Smith",
address => "123 Main St.",
city => "MyTown",
state => "MyState",
email => "bob@yahoo.com",
password => "password",
};
}
bless $self, $class;
return $self;
}
sub TO_JSON {
my $self = shift;
my $obj = {};
$obj->{$_} = $self->{$_} foreach grep { ! /^(email|password)$/ } (keys %$self);
return $obj;
}
sub save {
my $self = shift;
die "Cannot save without a valid filename!" if ! defined $self->{filename};
my $filename = $self->{filename};
my $json = JSON->new->allow_blessed(1)->convert_blessed(1);
my $data = $json->encode($self) or die "Invalid JSON conversion: $!";
open FP, ">$filename" or die "Cannot open $filename: $!";
print FP "$data\n";
close FP;
}
my $people_data = {
name => "Bob Smith"
address => "123 Main St.",
city => "MyTown",
state => "MyState",
email => "bob@yahoo.com",
password => "password"
};
my $people_data = {
name => "Bob Smith"
address => "123 Main St.",
city => "MyTown",
state => "MyState",
email => "bob@yahoo.com",
password => "password"
ignore_list => $ignore_list
};
{"name":"Bob Smith","address":"123 Main St.","city":"MyTown","state":"MyState","ignore_list":["entry1","entry2",…]}
{"name":"Bob Smith","address":"123 Main St.","city":"MyTown","state":"MyState","ignore_list":[{"name":"entry1",…},{"name":"entry2",…},…]}
irb> JSON::load(JSON::dump({1=>"a", :one =>"b", "1"=>"c", "one"=>"d"}))
=> {"1"=>"c", "one"=>"d"}
irb> YAML::load(YAML::dump({1=>"a", :one =>"b", "1"=>"c", "one"=>"d"}))
=> {1=>"a", :one=>"b", "1"=>"c", "one"=>"d"}
irb> Marshal::load(Marshal::dump({1=>"a", :one =>"b", "1"=>"c", "one"=>"d"}))
=> {1=>"a", :one=>"b", "1"=>"c", "one"=>"d"}
irb(main):009:0> JSON::load(JSON::dump([1, :one, "one"]))
=> [1, "one", "one"]
irb(main):010:0> YAML::load(YAML::dump([1, :one, "one"]))
=> [1, :one, "one"]
irb(main):011:0> Marshal::load(Marshal::dump([1, :one, "one"]))
=> [1, :one, "one"]
irb> JSON::load(JSON::dump({1=>"a", :one =>"b", "1"=>"c", "one"=>"d"}))
=> {"1"=>"c", "one"=>"d"}
irb> YAML::load(YAML::dump({1=>"a", :one =>"b", "1"=>"c", "one"=>"d"}))
=> {1=>"a", :one=>"b", "1"=>"c", "one"=>"d"}
irb> Marshal::load(Marshal::dump({1=>"a", :one =>"b", "1"=>"c", "one"=>"d"}))
=> {1=>"a", :one=>"b", "1"=>"c", "one"=>"d"}
irb(main):009:0> JSON::load(JSON::dump([1, :one, "one"]))
=> [1, "one", "one"]
irb(main):010:0> YAML::load(YAML::dump([1, :one, "one"]))
=> [1, :one, "one"]
irb(main):011:0> Marshal::load(Marshal::dump([1, :one, "one"]))
=> [1, :one, "one"]
The same would be true when using XML or YAML or SQL or "your own special" format.
The entire point of using a serializer (JSON, XML, whatever) is that you hand it a data structure and it returns a string which can be used to restore that data structure. Even in a non-dynamic language like C, the most you should have to do is save that string along with (maybe) a hint of the kind of structure to allocate when you want to load it back again.
You show an example of a Perl associative array, which by definition is virtually identical to a JSON object.
The problem is JSON doesn't understand classes, structures, many other kinds of hashes and associated arrays, and data types.
Nor does it understand relationships between classes and structures. It presumes a top down nested heirarchy.
Complex applications like muds aren't top down nested heirarchies (like documents).
They're full of cyclic object graphs, sometimes one-way, sometimes bi-directional.
And full serialization isn't really what we want anyway. It wouldn't be a DikuMUD (it'd be a MOO or MUSH then).
For example here's the Merc room…
Assuming we want to keep the one area to one file approach (and there are many reasons muds use it), you've got to produce a complete JSON parsable object.
Which means we have an area object, which contains arrays of resets, rooms, objects, shops, mob_progs, etcetera.
So just looking at the room struct…
It's got data we don't want to serialize, next, people, contents, area.
It has references we probably want to descend into and recursively serialize as arrays of objects within the object, extra_desc, exit[].
And when we descend in some records like exit, we'll find link references to rooms that we don't want to follow and instead
convert into vnums.
There is no easy peasy 2 line automated serialization whether the above be a C structure or a C++, Python, Perl, or Ruby class.
You will have to write a custom serialization routines, and for every new field you add to the serialization routine.
In order serialize in Ruby you'd add a to_json and self.create_json method. Similarly in Python. TO_JSON for Perl classes.
Here's some C JSON libraries…
http://sourceforge.net/projects/cjson/
https://github.com/json-c/json-c
http://www.digip.org/jansson/
This is the beginning of how one might dump a room to JSON using Merc and the cjson library.
You could of course make big architectural changes to your DikuMUD in order make it look more like like a JSON document.
If you think DikuMuds ought to be using JSON rather than their own special serialization, then you might want to show how much better it is.