NAME JSON::LINQ - LINQ-style query interface for JSON, JSONL, and LTSV files VERSION Version 1.01 SYNOPSIS use JSON::LINQ; # Read JSON file (array of objects) and query my @results = JSON::LINQ->FromJSON("users.json") ->Where(sub { $_[0]{age} >= 18 }) ->Select(sub { $_[0]{name} }) ->Distinct() ->ToArray(); # Read JSONL (JSON Lines) file - streaming, one object per line my @errors = JSON::LINQ->FromJSONL("events.jsonl") ->Where(sub { $_[0]{level} eq 'ERROR' }) ->ToArray(); # Read LTSV (Labeled Tab-Separated Values) file - streaming my @rows = JSON::LINQ->FromLTSV("access.ltsv") ->Where(sub { $_[0]{status} eq '200' }) ->ToArray(); # DSL syntax for simple filtering my @active = JSON::LINQ->FromJSON("users.json") ->Where(status => 'active') ->ToArray(); # Grouping and aggregation my @stats = JSON::LINQ->FromJSON("orders.json") ->GroupBy(sub { $_[0]{category} }) ->Select(sub { my $g = shift; return { Category => $g->{Key}, Count => scalar(@{$g->{Elements}}), Total => JSON::LINQ->From($g->{Elements}) ->Sum(sub { $_[0]{amount} }), }; }) ->OrderByDescending(sub { $_[0]{Total} }) ->ToArray(); # Write results back as JSON, JSONL, or LTSV JSON::LINQ->From(\@results)->ToJSON("output.json"); JSON::LINQ->From(\@results)->ToJSONL("output.jsonl"); JSON::LINQ->From(\@results)->ToLTSV("output.ltsv"); # JOIN: main JSON table x sub-table LTSV (department lookup) my $depts = JSON::LINQ->FromLTSV("departments.ltsv"); my @joined = JSON::LINQ->FromJSON("employees.json") ->Join($depts, sub { $_[0]{dept_id} }, sub { $_[0]{id} }, sub { { name => $_[0]{name}, dept => $_[1]{name} } }) ->ToArray(); # JOIN: main LTSV log x sub-table JSON (price master) my $prices = JSON::LINQ->FromJSON("prices.json"); my @priced = JSON::LINQ->FromLTSV("orders.ltsv") ->Join($prices, sub { $_[0]{sku} }, sub { $_[0]{sku} }, sub { { order_id => $_[0]{id}, amount => $_[0]{qty} * $_[1]{price} } }) ->ToArray(); # Boolean values my $rec = { active => JSON::LINQ::true, count => 0 }; DESCRIPTION JSON::LINQ provides a LINQ-style query interface for JSON, JSONL (JSON Lines), and LTSV (Labeled Tab-Separated Values) files. It is the JSON counterpart of LTSV::LINQ, sharing the same LINQ API and adding JSON- and LTSV-specific I/O methods. Key features: * Lazy evaluation - O(1) memory for JSONL and LTSV streaming * Method chaining - Fluent, readable query composition * DSL syntax - Simple key-value filtering without code references * 65 LINQ methods - including JSON I/O (FromJSON, FromJSONL, FromJSONString, ToJSON, ToJSONL), LTSV I/O (FromLTSV, ToLTSV), and all 60 methods from LTSV::LINQ * Built-in JSON parser - No CPAN JSON module required * Pure Perl - No XS dependencies * Perl 5.005_03+ - Works on ancient and modern Perl INCLUDED DOCUMENTATION The eg/ directory contains sample programs: eg/01_json_query.pl FromJSON/Where/Select/OrderByDescending/Distinct/ToLookup eg/02_jsonl_query.pl FromJSONL streaming, GroupBy, aggregation, ToJSONL eg/03_grouping.pl GroupBy, ToLookup, GroupJoin, SelectMany, Join eg/04_sorting.pl OrderBy/ThenBy multi-key sort, OrderByNum vs OrderByStr eg/05_json_ltsv_join.pl JOIN main JSON x sub-table LTSV eg/06_ltsv_json_join.pl JOIN main LTSV x sub-table JSON The doc/ directory contains JSON::LINQ cheat sheets in 21 languages: doc/json_linq_cheatsheet.EN.txt English doc/json_linq_cheatsheet.JA.txt Japanese doc/json_linq_cheatsheet.ZH.txt Chinese (Simplified) doc/json_linq_cheatsheet.TW.txt Chinese (Traditional) doc/json_linq_cheatsheet.KO.txt Korean doc/json_linq_cheatsheet.FR.txt French doc/json_linq_cheatsheet.ID.txt Indonesian doc/json_linq_cheatsheet.VI.txt Vietnamese doc/json_linq_cheatsheet.TH.txt Thai doc/json_linq_cheatsheet.HI.txt Hindi doc/json_linq_cheatsheet.BN.txt Bengali doc/json_linq_cheatsheet.TR.txt Turkish doc/json_linq_cheatsheet.MY.txt Burmese doc/json_linq_cheatsheet.TL.txt Filipino doc/json_linq_cheatsheet.KM.txt Khmer doc/json_linq_cheatsheet.MN.txt Mongolian doc/json_linq_cheatsheet.NE.txt Nepali doc/json_linq_cheatsheet.SI.txt Sinhala doc/json_linq_cheatsheet.UR.txt Urdu doc/json_linq_cheatsheet.UZ.txt Uzbek doc/json_linq_cheatsheet.BM.txt Malay TARGET USE CASES * Querying JSON API response files * Streaming analysis of JSONL log files * Joining JSON master tables with LTSV log files (or vice versa) * Data transformation pipelines (JSON in, JSON/JSONL/LTSV out) * In-memory array queries using LINQ-style API * Systems where no CPAN JSON module is available DATA SOURCES FromJSON($file) Read a JSON file containing a top-level array. The entire file is parsed once into memory, then iterated lazily. FromJSONL($file) Read a JSONL file. Each non-empty line is parsed as a separate JSON value. Lazy: one line at a time. O(1) memory usage. FromJSONString($json) Parse a JSON string and iterate its elements. FromLTSV($file) Read an LTSV (Labeled Tab-Separated Values) file. Each line is split on TAB, and each field on the first colon, producing a hash reference per record. Lazy: one line at a time. O(1) memory. From(\@array) Query an in-memory Perl array. Range($start, $count) Generate an integer sequence. Empty() Return an empty sequence. Repeat($element, $count) Repeat one element N times. LINQ METHODS (65) Data Sources: From, FromJSON, FromJSONL, FromJSONString, FromLTSV, Range, Empty, Repeat Filtering: Where (with DSL key=>value form) Projection: Select, SelectMany Concatenation: Concat, Zip Partitioning: Take, Skip, TakeWhile, SkipWhile Ordering: OrderBy, OrderByDescending, OrderByStr, OrderByStrDescending, OrderByNum, OrderByNumDescending, Reverse, ThenBy, ThenByDescending, ThenByStr, ThenByStrDescending, ThenByNum, ThenByNumDescending Grouping: GroupBy Set ops: Distinct, Union, Intersect, Except Joins: Join, GroupJoin Quantifiers: All, Any, Contains, SequenceEqual Element: First, FirstOrDefault, Last, LastOrDefault, Single, SingleOrDefault, ElementAt, ElementAtOrDefault Aggregation: Count, Sum, Min, Max, Average, AverageOrDefault, Aggregate Conversion: ToArray, ToList, ToDictionary, ToLookup, ToJSON, ToJSONL, ToLTSV, DefaultIfEmpty Utility: ForEach INSTALLATION Standard CPAN installation: cpan JSON::LINQ Or manually: perl Makefile.PL make make test make install No C compiler required. No non-core CPAN dependencies. COMPATIBILITY Perl 5.005_03 and later. Tested on Perl 5.005_03 through 5.42. Works on Windows and UNIX/Linux. Pure Perl, no XS. LIMITATIONS * Query objects can only be consumed once (iterator is exhausted after a terminal method). Re-create the query to re-iterate. * FromJSON loads the entire file into memory. Use FromJSONL for large files where streaming matters. * The built-in JSON parser does not support surrogate pairs (\uD800-\uDFFF) or circular reference detection in encoding. * ToLTSV sanitizes TAB/CR/LF in field values to single space to preserve the LTSV record/field structure. * The iterator protocol uses undef to signal end-of-sequence, so a JSON null cannot appear as a top-level element of a sequence. A Select() that projects a nullable JSON field will be truncated at the first null. Project to a sentinel value (0, '', or {}), or wrap each element in a hashref so the element itself is never undef. See "Iterator Protocol and JSON null" in the POD. AUTHOR INABA Hitoshi SEE ALSO LTSV::LINQ - The LTSV counterpart of this module mb::JSON - The JSON encoder/decoder this module's parser derives from JSONL spec - https://jsonlines.org/ LTSV spec - http://ltsv.org/ LINQ ref - https://docs.microsoft.com/dotnet/api/system.linq COPYRIGHT AND LICENSE Copyright (c) 2026 INABA Hitoshi This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.