Poked at the expression builder for a bit and figured out a way to dynamically output columns with desired name prefix as single json string or null (if empty). It's a bit complicated and it can probably be improved, but it works natively in Azure Data Factory expression builder for a derived column. I'm doing this on multiple derived columns to reduce 280 columns (most empty) down to 5. Just replace the two instances of 'tagColumn/' with the desired filter.
reduce(mapIf(mapAssociation(keyValues(columnNames(), array(toString(columns()))), @(key = #key, value = #value)), and(startsWith(#item.key, 'tagColumn/'), not(isNull(#item.value))), concat('"', replace(#item.key, 'tagColumn/'), '":"', #item.value, '"')), "", iif(notEquals(#acc, ''), #acc + ',' + toString(#item), #acc + toString(#item)), iif(toString(#result) != '', '{' + toString(#result) + '}', toString(null())))