File: Json.pm

package info (click to toggle)
libur-perl 0.470%2Bds-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 7,184 kB
  • sloc: perl: 61,813; javascript: 255; xml: 108; sh: 13; makefile: 9
file content (133 lines) | stat: -rw-r--r-- 3,403 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
package UR::Object::View::Default::Json;

use strict;
use warnings;
require UR;
our $VERSION = "0.47"; # UR $VERSION;

use JSON;

class UR::Object::View::Default::Json {
    is => 'UR::Object::View::Default::Text',
    has_constant => [
        toolkit     => { value => 'json' },
    ],
    has_optional => [
        encode_options => { is => 'ARRAY', default_value => ['ascii', 'pretty', 'allow_nonref', 'canonical'], doc => 'Options to enable on the JSON object; see the documentation for the JSON Perl module' },
    ],
};

my $json;
sub _json {
    my ($self) = @_;
    return $json if defined $json;

    $json = JSON->new;
    foreach my $opt ( @{ $self->encode_options } ) {
        local $@;
        eval { $json = $json->$opt; };
        if ($@) {
            Carp::croak("Can't initialize JSON object for encoding.  Calling method $opt from encode_options died: $@");
        }
        if (!$json) {
            Carp::croak("Can't initialize JSON object for encoding.  Calling method $opt from encode_options returned false");
        }
    }
    return $json;
}

sub _generate_content {
    my $self = shift;
    return $self->_json->encode($self->_jsobj);
}

sub _jsobj {
    my $self = shift;

    my $subject = $self->subject();
    return '' unless $subject;

    my %jsobj = ();

    for my $aspect ($self->aspects) { 
        my $val = $self->_generate_content_for_aspect($aspect);
        $jsobj{$aspect->name} = $val if defined $val;
    }

    return \%jsobj;
}

sub _generate_content_for_aspect {
    my $self = shift;
    my $aspect = shift;

    my $subject = $self->subject;
    my $aspect_name = $aspect->name;

    my $aspect_meta = $self->subject_class_name->__meta__->property($aspect_name);
    #warn $aspect_name if ref($subject) =~ /Set/;

    my @value;
    local $@;
    eval {
        @value = $subject->$aspect_name;
    };
    if ($@) {
        warn $@;
        return;
    }

    # Always look for a delegate view.
    # This means we replace the value(s) with their
    # subordinate widget content.
    unless ($aspect->delegate_view) {
        $aspect->generate_delegate_view;
    }

    my $ref = [];

    if (my $delegate_view = $aspect->delegate_view) {
        foreach my $value ( @value ) {
            if (Scalar::Util::blessed($value)) {
                $delegate_view->subject($value);
            } else {
                $delegate_view->subject_id($value);
            }
            $delegate_view->_update_view_from_subject();

            if ($delegate_view->can('_jsobj')) {
                push @$ref, $delegate_view->_jsobj;
            } else {
                my $delegate_text = $delegate_view->content();
                push @$ref, $delegate_text;
            }
        }
    }
    else {
        for my $value (@value) {
            if (ref($value)) {
                push @$ref, 'ref';  #TODO(ec) make this render references
            } else {
                push @$ref, $value;
            }
        }
    }

    if ($aspect_meta && $aspect_meta->is_many) {
        return $ref;
    } else {
        return shift @$ref;
    }
}

# Do not return any aspects by default if we're embedded in another view
# The creator of the view will have to specify them manually
sub _resolve_default_aspects {
    my $self = shift;
    unless ($self->parent_view) {
        return $self->SUPER::_resolve_default_aspects;
    }
    return ('id');
}

1;