jlb333333 has asked for the wisdom of the Perl Monks concerning the following question:

Hi.

I am trying to modify the input data structure of json data.

Current structure:

{"OWNER":"KeyProjects","Region":"Southern","District":"Arid","PLANTNO" +:"Sunset View","COMPT":"A08","age1":null,"ht1":null,"age2":null,"ht2" +:null,"age3":null,"ht3":null,"age4":null,"ht4":null,"age5":null,"ht5" +:null,"age6":null,"ht6":null,"age1":null,"ht1":null,"age2":null,"ht2" +:null,"age3":null,"ht3":null,"age4":null,"ht4":null,"age5":null,"ht5" +:null,"age6":null,"ht6":null,"wc":"EF1"},

I want it to look like this:

{"OWNER":"KeyProjects","Region":"Southern","District":"Arid","PLANTNO" +:"Sunset View","COMPT":"A08","scheduled":{"age1":null,"ht1":null,"age +2":null,"ht2":null,"age3":null,"ht3":null,"age4":null,"ht4":null,"age +5":null,"ht5":null,"age6":null,"ht6":null},"completed":{"age1":null," +ht1":null,"age2":null,"ht2":null,"age3":null,"ht3":null,"age4":null," +ht4":null,"age5":null,"ht5":null,"age6":null,"ht6":null},"wc":"EF1"}

(two sections are now nested(extra{}s), with the words "scheduled" and "completed" added).

The fields of the original data vary in length so simply counting characters to find an insert point will not help.

Just can't get perl regex to do what I want it to do.

Assistance would be greatly appreciated

John

Replies are listed 'Best First'.
Re: Find a Position and Insert Text
by Your Mother (Archbishop) on Mar 15, 2016 at 18:05 UTC

    Because I'm sick of trying to solve my own problems. :P

    #!/usr/bin/env perl use strictures; use JSON; use Data::Dump "dump"; use Test::More; my $in = decode_json '{"OWNER":"KeyProjects","Region":"Southern","Dist +rict":"Arid","PLANTNO":"Sunset View","COMPT":"A08","age1":null,"ht1": +null,"age2":null,"ht2":null,"age3":null,"ht3":null,"age4":null,"ht4": +null,"age5":null,"ht5":null,"age6":null,"ht6":null,"age1":null,"ht1": +null,"age2":null,"ht2":null,"age3":null,"ht3":null,"age4":null,"ht4": +null,"age5":null,"ht5":null,"age6":null,"ht6":null,"wc":"EF1"}'; my $out = decode_json '{"OWNER":"KeyProjects","Region":"Southern","Dis +trict":"Arid","PLANTNO":"Sunset View","COMPT":"A08","scheduled":{"age +1":null,"ht1":null,"age2":null,"ht2":null,"age3":null,"ht3":null,"age +4":null,"ht4":null,"age5":null,"ht5":null,"age6":null,"ht6":null},"co +mpleted":{"age1":null,"ht1":null,"age2":null,"ht2":null,"age3":null," +ht3":null,"age4":null,"ht4":null,"age5":null,"ht5":null,"age6":null," +ht6":null},"wc":"EF1"}'; my $planned = qr/\A (?: age\d+ | ht\d+ ) \z/x; my $corrected = $in; for my $key ( keys %{$corrected} ) { if ( $key =~ $planned ) { $corrected->{completed}{$key} = $corrected->{scheduled}{$key} += delete $corrected->{$key}; } } # print dump $in; is_deeply $out, $corrected, "Corrected data matches expectations"; diag encode_json $corrected; done_testing();

      Thank you for your reply and code.

      This is just way too advanced for me at present.

      I am still learning Perl etc.

      John

        I totally understand. I remember the same boat quite well. That said, the solution, or at least its style, I gave is the only sane way to approach your problem and by far the easiest. Regular expressions can indeed move mountains but it's much harder than you're thinking and for your problem I doubt you (or anyone for that matter) would ever arrive at anything that worked except in the most trivial and inflexible case.

        My code was idiomatic but it is easy and straightforward once you can follow it. It's also robust whereas a regex solution will never be. I'll adapt the code a bit to make it more clear and walk you through it. <readmore/> away…

        Have fun, HTH, TTFN, etc. :P

        Further Reading

        Update: </c></c> fixed.

Re: Find a Position and Insert Text
by Corion (Patriarch) on Mar 15, 2016 at 17:53 UTC

    So, what code have you already written and how did it fail?

    The easiest way in my opinion would be to find the keys where you need to insert the two new structures, and replace them:

    use strict; my $str = '{"OWNER":...}'; $str =~ s!"age1"!"scheduled":{"xage1"!; $str =~ s!"age1"!}, "completed":{"xage1"!; $str =~ s!"wc"!}, "wc"!; $str =~ s!"xage1"!"age1"!g;

    I've first replaced age1 by xage1 so that on the second replacement, I can use "completed" without undoing my first replacement.

      Thank you for your reply and code.

      I was able to use your code to solve the problem.

      Sometimes one just needs a nudge in the right direction

Re: Find a Position and Insert Text
by toolic (Bishop) on Mar 15, 2016 at 17:51 UTC